home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
basic
/
glib19.zip
/
GLIB19.DOC
< prev
next >
Wrap
Text File
|
1991-06-27
|
204KB
|
5,480 lines
GLIB version 1.90
Released: June, 1991
Copyright InfoSoft, 1986-1990, 1991
Note: This release is intended for QB 4.5 ONLY !
For BASIC PDS 7.x support, get GLib 2.01x
The files that should be included on this disk or .ZIP are:
GLIB19.NEW - Overview of new features in GLib 1.9
GLIB19.DOC - Complete Library documentation.
MACRO19.DOC - Documentation for care and feeding of the
Macro Field Editor, QCalc, Clock, DialogBox
and Status Line 'macro' Routines.
GLIBXTD.BI - BASIC include file of declarations for ALL
GLib 1.9 routines (for reference use).
GLIB19.QLB - The routines for use with QB4 environment.
GLIBDEMO.BAS - A QB demo of some of the routines.
QCALCDEM.BAS - Brief demo of the QCALC routine.
MFEDDEMO.BAS - Demo of MFed, text input handler.
EMP.DAT - Sample data file for MFEDDEMO.BAS
MAILERG - Quick Mailer for registering.
LIST.ME - Any last minute thoughts or notes
Upon registering, users will also receive a Quick Reference guide
to using the routines (GLIB19.QRF).
Copyright (C) InfoSoft, 1986-1990, 1991 1
License, Terms and Use:
Under no circumstances may these routines be distributed
individually or without the accompanying documentation, which is an
integral part of the package, nor may the documentation be altered in
anyway. This includes, but is not limited to distributing GLIB19.QLB
for use in executing applications compiled to BRUN format.
Under no circumstances may the routines in the GLIB package,
source, object files, libraries or documentation be distributed by or
otherwise become a part of, or affiliated with any group or
organization involved in the distribution of what is generally been
come to be known as SHAREWARE for disk or distribution fees, or for
fees of any sort without my express WRITTEN consent. This includes
supplying the routines, library and or documentation for so-called
disk fees.
Finally, we make no claims that the routines herein will fit
your needs, simply that in all testing and prior use that they worked
for us and that you may find them interesting and helpful in your
programming. Any liability for the use, misuse or inability to use
the GLIB routines or libraries, is solely the users.
1. GLIB Compatibility
Unless otherwise noted, all routines used in GLIB are written
in assembler with MASM 5.1. The few BASIC based routines that there
are, were written under QB 4.5 or the MS BASIC PDS Compiler 7.x.
DO NOT attempt to combine older QB3 routines with QB4x
routines into a QB4 compiled program or library. ASM based routines
require significant conversion for use under QB4. Linking QB3 and QB4
BASIC based routines will require that both runtime modules be used,
BCOM/BRUN30 and BCOM/BRUN40 - which WILL yield certain disaster.
2. Support
As long as it exists, I will support and entertain questions
regarding QB and/or GLIB via the QuickBASIC conference on The
Information Booth, (316) 684 8744, 1200 - 2400 bps, 24 hrs.
If you have a problem with GLIB, you _MUST_ be prepared to
supply supporting source code demonstrating the problem you are
having. I am more than a little interested in any GLib or QB bugs
that you might find, but I do not have the time to track down problems
based on vague descriptions of problems when I cannot see if you are
using the sub program right. PLEASE do not waste my time with gen-
eral, vague inquiries without supporting source examples - I do not
need and cannot use .EXE files.
Copyright (C) InfoSoft, 1986-1990, 1991 2
3. Terms of usage
You are granted free and unlimited personal use of any and all
routines in the environment library (".QLB") for GLIB 1.9 that you may
find of value. Furthermore, you are free to pass along the BBS
distribution files (listed at the start of this document) as long as
they are passed along as a whole according to the guidelines listed
above.
No one is granted any permission to share or pass along the
BCOM library (".LIB") or any object files. As distributed, the GLIB
documentation, demo or tutor and the environment library (".QLB")
provide you with everything you need to call and execute GLIB routines
from within the editor/environment. Furthermore, as described above
you are given unlimited rights for such use. This provides an ex-
tremely generous forum for purposes of sampling, testing and evalua-
tion and allows unlimited latitude in terms of personal use or as a
tutorial regarding some of the more advanced features in today's
QuickBASIC. Note that this personal use does not include any rights
to distribute the .QLB as a runtime module. That is, if your sole
intent with GLib is personal use or experimental use from within the
environment, no monies are requested, expected or solicited.
However, you might find some of the routines of value and want
to incorporate them into a standalone .EXE applications. In this
case, the library (.LIB) of routines and permission to use them in
such applications may be purchased as described in item (4) below.
4. License terms
If you choose to purchase a LIBRARY/OBJECT module license,
implicit in that, is the specific rights to use the routines in GLIB
in your standalone runtime program either by direct linking or the use
of the BUILDRTM program in BASIC PDS. This further includes the
supplying the QuickLibrary (QLB) as a runtime module if that is your
desire, however this method does not either implicitly or explicitly
bequeath another or secondary LIBRARY/OBJECT module license to any end
user(s) or people receiving that as a run time module. The routines
may only be passed along in linked form, as a QLB or EXE file, never
as an OBJECT module or in LIBRARY form.
A LIBRARY/OBJECT module license is grated only to the person or
company providing payment or named on the mailer. No grandfather,
parent or child usage rights are implied or granted. That is, a
LIBRARY license purchased by an individual grant the usage of the
library by that individual, not their employer or anyone outside the
immediate family. Conversely, a license purchased by a company,
corporation, business or government organization does not imply or
grant any person employed, allied or associated with that organization
personal usage rights without purchasing a LIBRARY/OBJECT license.
Copyright (C) InfoSoft, 1986-1990, 1991 3
5. Purchasing GLIB
To get the latest version of GLIB as well as the standalone
library (.LIB):
a. QB Version Support
We will no longer compile current code for all previous
versions of QB. The chart below defines those GLib Libraries avail-
able for the various QB version over the last few years.
QB 4.0 QB 4.00(a / b) QB 4.5 BASIC PDS 7.x
GLib 2.0?/x X
GLib 1.9 X
**GLib 1.7 X X
** Version 1.7 is a past release, but since it is the last to
support QB 4.0, QB 4.0(a), QB 4.00(b) and BASCOM 6.00, we will
continue to support it (and it alone) for those still using
those QB versions.
b. First Time buyers:
Fill out the enclosed mailer, with $40 in checks or money
orders (these must be payable in US Funds) and mail it to the address
on the mailer. You'll receive, by return mail a diskette containing
complete documentation, object files, .LIB and .QLB for release 1.9.
c. Upgrading a previous GLib version:
Upgrades from GLib 1.7 with your serial number are $15.00
Upgrades from GLib 1.7 without serial number,
as well as GLib version 1.6/1.65 are $20.00
Upgrades from GLib 1.5 and before are $30.00
Fill out the mailer, indicating an upgrade and the version
originally purchased and send it back with US Funds, and we'll mail
out an upgrade diskette.
d. In ALL cases, you MUST use the mailer so that we can identify
diskette type, QB version etc. Please allow 4-5 weeks for delivery.
Mailing Address:
InfoSoft
GLIB 1.9
PO Box 782057
Wichita, Ks
67278-2057
Copyright (C) InfoSoft, 1986-1990, 1991 4
GLIB 1.9 Functions and Sub Programs
-----------------------------------
NOTE WELL: All but a very, very few GLib functions are in ass-
embler. As such, the data type you pass is VERY important. Unless
otherwise specified, all numbers are INTEGERS, so assume a trailing
'%' unless otherwise noted. This pertains to FUNCTIONS too: Ansi-
Loaded is AnsiLoaded% unless DEFINT A-Z is in effect. Likewise,
string lengths can be critical and care should be taken to note and
pass the required length for correct results.
Name: AnsiLoaded Type: FUNCTION
Syntax: RCode = AnsiLoaded
This simply returns an integer indicating is ANSI.SYS (or
compatible) is loaded as a device driver. If loaded, it returns non
Zero and if not, it returns zero. This can helpful in determining
whether to use DPRINT (qv) or not.
Name: ArgCnt Type: FUNCTION
Syntax: qargs = ArgCnt
ArgCnt may also be invoked with the 'C' like name of 'argc'.
Returns the number of arguments in the command tail delimited by a
space. That is, with 'FOOBAR.EXE /qwerty /1 /2 /3 /4', ArgCnt would
return 5 as the number of command tail arguments. ArgCnt can also be
called by the 'C'-like name of argc. See also ArgVar and GetCmdTail.
ArgVar and ArgCnt replace the interim routine CmdLine. Example:
PRINT "Number of command line arguments is: "; ArgCnt
Name: ArgVar Type: FUNCTION
Syntax: var$ = ArgVar$(arg)
ArgVar may also be invoked with the 'C' like name of 'argv'.
ArgVar is the complementary routine to ArgCnt(qv) by returning a
specified argument from the command tail in the programs PSP. ArgVar
returns a string variable representing the unparsed, specified argu-
ment from the command tail. To fetch the entire command tail see
GetCmdTail. As with ArgCnt and GetCmdTail, ArgVar deals with the
ACTUAL command tail found in the program's PSP, so accommodations
should be made for when your program running as a QB file versus as a
EXE (see QBLoaded). Example - Print all command tail elements:
FOR x = 1 to argc
PRINT argv$(x) ' prints them one-by-one
NEXT x
Copyright (C) InfoSoft, 1986-1990, 1991 5
Name: AttrMake Type: FUNCTION
Syntax: attr = AttrMake(Fg, Bg)
Converts 2 integers representing the fore and background colors
into a single integer representing the attribute. Example:
Attr = AttrMake(14, 4) ' returns 78
Name: AttrRev Type: FUNCTION
Syntax: NewAttr = AttrRev(Attr)
Reverses a passed attribute byte from fg/bg to bg/fg. When
highlighting a portion of the screen, this can be faster than separate
steps:
CALL AttrSplit(attr, fg, bg) \
SWAP fg, bg > NewAttr = AttrRev(attr)
NewAttr = AttrMake(fg, bg) /
Name: AttrSplit Type: SUB
Syntax: CALL AttrSplit(Attr, Fg, Bg)
UnConverts a single integer representing the attribute into 2
integers representing the fore and background colors. This assumes a
legitimate attribute value. Example:
CALL AttrSplit(78, fg, bg) ' fg = 14, bg=4
Name: BCD2Int / Int2BCD Type: FUNCTION
Syntax: IntVal = BCD2Int(BCDVal)
BCDVal = Int2BCD(IntVal)
Many times when dealing with DOS directly, you need Binary Coded
Decimal values (such as when tinkering with DOS file dates and/or
times). These 2 routines allows you to quickly encode or decode BCD
values.
Name: BitChkInt/BitClrInt/BitSetInt Type: FUNCTION
Syntax: result = BitChkInt(IValue, bit)
result = BitClrInt(IValue, bit)
result = BitSetInt(IValue, bit)
Allows you to CHECK, CLEAR or SET a specific bit in an integer
value. Such integer bit coding allows you to store several values or
flags in a single integer. Since an integer is 16 bits, up to 16
different flags or other 0/1 values could be stored on disk in the
space of 2 bytes. See also Bit---Lng. Note that BitClrLng and
BitSetLng both return new integers representing the new value with the
desired bits cleared or set.
Copyright (C) InfoSoft, 1986-1990, 1991 6
Name: BitChkLng/BitClrLng/BitSetLng Type: FUNCTION
Syntax: result& = BitChkLng(LValue&, bit)
result& = BitClrLng&(LValue&, bit)
result& = BitSetLng&(LValue&, bit)
Allows you to CHECK, CLEAR or SET a specific bit in an long
value.Long integer bit coding allows you to store up various values or
flags in a long integer. Since a long integer is 32 bits, up to 32
different flags or other 0/1 values could be stored on disk in the
space of 4 bytes. See also Bit---Int. Note that BitClrLng and
BitSetLng both return new long integers representing the new value
with the desired bits cleared or set.
Name: Boxes Type: SUB
Syntax: CALL Boxes(TRow, LCol, BRow, LCol, frame, attr)
BOXES is similar to the windows sub in that it puts frame like
items on the screen. BOXES differs from WINDOWS in that a wider
selection of frame styles are offered, fewer parameters are passed and
without the label centering code, sound effects and the like, it is
slightly faster. The first four parameters mark the perimeter of the
box to draw and 'attr' indicates the color attribute to use on the
frame and interior. The frame parameter may range from 0 to 9 to
indicate the style of frame to use:
0 - Spaces used as border
1 - Double / Double ( )
2 - Double Horz / Single Vert ( )
3 - Single / Single ( )
4 - Single Horz / Double Vert ( )
5 - Medium Thick boxes (ASCII 220-223)
6 - thick boxes (ASCII 219, 219, 221, 222
7 - ASCII 176 used
8 - ASCII 177 used
9 - ASCII 178 used
Name: BoxesFrame Type: SUB
Syntax: CALL BoxesFrame(TRow, LCol, BRow, LCol, frame, attr)
BoxesFrame is almost identical to Boxes except that the interior
is hollow. This allows you to pop a box onto the screen framing
existing text without disturbing that text.
Name: BShadow Type: SUB
Syntax: CALL BShadow( 0 | 1 )
This is used to indicate to the Library that all subsequent calls
to Boxes should automatically include a 3-D shadow effect. Calling it
with a non zero (1) parameter turns on shading, while zero turns it
off. Use this to also control the shading effect in FlexMenu (aka
MenuChoice). Do not confuse this with WShadow which control which
SIDE the windows shadowing takes place on.
Copyright (C) InfoSoft, 1986-1990, 1991 7
Name: BufferCalc Type: FUNCTION
Syntax: size = BufferCalc(Trow, LCol, Brow, Rcol)
Given a set of coordinates, BufferCalc returns an integer indicat-
ing the number of bytes indicating the size an array would have to be
to hold such a section of the screen. This can be very useful when
used to size an array for use with SaveWdw - RestWdw. Example:
size = BufferCalc(1, 1, 12, 40)
REDIM ScrnArry(size)
CALL SaveWindow(ScrnArry(1), 1, 1, 12, 40)
Name: Chirp Type: SUB
Syntax: CALL Chirp(x)
This routine is used to sound the speaker in a fast tone of either
ascending or descending pitch. The same method is used in WDW to make
the popping sound. CHIRP is provided to allow you to make a un-
popping sound when removing a window. There are 2 modes in the CHRP
routine:
mode 1 = ascending frequency (up)
2 = descending frequency (down)
Example:
m=1
CALL CHIRP(m) ' will sound a "chirp" of ascending frequency
' as will:
CALL CHIRP(1)
Name: Chk286 Type: FUNCTION
Syntax: retc = Chk286
Provides a quick check as to whether a 80286 processor is in-
stalled in the machine. This can help determine the speed of certain
loops in games or other timing dependant loops. A non zero return
indicates true, and zero indicates false. This is called internally
by some GLib routines to check if a feature or function is systemical-
ly available.
Name: CLon / CLoff Type: SUB
Syntax: CALL CLON : CALL CLOFF
Neither of these take an argument or pass a parameter. They
simply engage (CLON) or disengage (CLOFF) the Caps Lock state.
Name: Clock Type: SUB
Syntax: CALL Clock(Row, Col, Attr, Install)
(CLOCK is documented in MACROxx.DOC). Row and Col are the (Tr,
Lc) coordinates for the display, attr is the color to use and Install
is 0, 1 or 2 for Uninstall, Install or install quiet mode.
Copyright (C) InfoSoft, 1986-1990, 1991 8
Name: ClrEOL Type: SUB
Syntax: CALL ClrEOL(row, col, attr%)
Clears the video display from the specified (row, col) using the
specified attribute to the End Of the Line. See also ClrSOL, ClrSOS
and ClrEOS.
Name: ClrEOS Type: SUB
Syntax: CALL ClrEOS(row, col, attr%)
Clears the video display from the specified (row, col) using the
specified attribute to the End Of the Screen. See also ClrSOL, ClrSOS
and ClrEOL.
Name: ClrSOL Type: SUB
Syntax: CALL ClrSOL(row, col, attr%)
Clears the specified line on the video display from column 1 to
the specified (row, col) using the specified attribute. See also
ClrEOS,ClrSOS and ClrEOL.
Name: ClrSOS Type: SUB
Syntax: CALL ClrSOS(row, col, attr%)
Clears the video display from Start of the Screen to the specified
(row, col) using the specified attribute. See also ClrEOS, ClrSOL and
ClrEOL.
Name: ClrKBD Type: SUB
Syntax: CALL ClrKBD
Clear the keyboard buffer of any and all waiting keystrokes. This
is an effective way of eliminating type-ahead in critical portions of
your program. See also KBStuff.
Name: CPUInfo Type: FUNCTION
Syntax: support = CPUInfo(Model, SubModel, BiosRev, CPUType,_
NDPType)
This is a very comprehensive system identification routine. The
PC BIOS contains several bytes which can be used to determine the type
of PC it is and whether it is a newer or later model. If an earlier
PC system does not support the SubModel and BiosRev bytes, the func-
tion will return non zero in support to indicate this. Most PC's
after 1984 will support this.
This routine returns several things:
1) Model - This byte identifies the type or class of machine.
2) SubModel - This identifies similar type systems from one
another, such as a Model 50 from a Model 60 or a 286 based system.
Copyright (C) InfoSoft, 1986-1990, 1991 9
3) BIOS Rev - The BIOS Revision byte helps further distinguishes
PC systems - such as the original IBM AT (6 Mhz) from the
later Model 339 (8 MHz).
PC Systems table:
Model Sub Mod BIOS rev
255 -- -- Orig. IBM PC type (all PC's to 10/82)
255 -- -- Original IBM XT's thru 8/82
255 -- -- Later IBM XT, XT/370 (11/82)
254 -- -- XT, 3270PC, IBM Portables
251 00 01 XT's 1/10/1986
251 00 02 640 kb XT - 5/09/1986
253 -- -- PCjr (6/1/83)
252 -- -- IBM AT dated 1/10/84
252 00 01 286 Systems
252 01 00 286 Systems (ca 11/85)
252 04 00 PS/2 Model 50
252 05 00 PS/2 Model 60
250* 00 00 PS/2 Model 30
249 -- -- Convertible
248 00 00 PS/2 Model 80
Other
2d Compaq PC 4.77 (Mhz)
9a Compaq Plus (XT type)
* We believe that the Model 25 shares this ID bytes with Model 30,
but has a different sub model or BIOS rev identifier.
4) CPU type installed, NDP type:
CPU returns the significant numbers in the central processor iden-
tification and NDP returns info on any numerical co-processor:
Type CPU parameter Type NDP parameter
---- ------------- ---- -------------
8086 86 None 0
NEC V30 30 8087 87
8088 88 80287 287
NEC V20 20 80387 387
80186 186
80188 188
80286 286
80386 386
Copyright (C) InfoSoft, 1986-1990, 1991 10
Name: CRTSwap Type: SUB
Syntax: CALL CRTSwap(Crt, Mode)
CRTSwap swaps the primary and alternate display, making the
primary display that indicated in the call. This means future QPRINT
and Save/RestoreScreen calls will act on the new monitor. BASIC's
PRINT will continue to output to the initial display because QB, like
your programs, looks at the equipment list only once at the start of
the program and will not "notice" that you changed CRT's. QPRINT and
other video routines like Save/Restore Screen determine the active CRT
each time they are called and thus will act upon the new primary
display.
When calling CRTSwap, you tell it which CRT to activate:
0 = MONO, 1 = CGA, 2= EGA/VGA. Additionally, you tell it what
video mode to put it in (not to be confused with the BASIC SCREEN
function), by passing the mode. In general, when making a MONO CRT
the primary display, 7 is the mode you will use, but CRTSwap does no
checking for this. In setting the new mode, the new primary screen is
inherently cleared. Example:
CONST EGA = 3, MONO = 0 ' make MONO active in mode 7
CALL CRTSwap(MONO, 7) ' PRINT to go to org display,
' QPRINT to MDA
..
..
CALL CRTSwap(EGA, 3) ' make EGA active in mode 3
' PRINT goes to EGA, QPRINT to
' EGA
Name: CtrlPrtSc Type: SUB
Syntax: CALL CtrlPrtSc
The same as entering Ctrl-PrtSc from the keyboard: turns on
continuous printing. Note that this may have no effect on systems
with keyboard enhancers installed.
Name: CvtAlt Type: FUNCTION
Syntax: retc = CvtAlt(x$)
Returns the ASCII value of the letter used in with an [Alt-?]
combination. If x$ is [Alt-Q], then retv returns from CvtAlt as 81
which is ASC("Q"). This is useful in simplifying CASE structures
which need to act on a wide variety of input possibilities. All such
[Alt-?] key combinations have a length of 2 and CvtAlt will only
attempt to translate strings that are 2 character long, or CvtAlt
will return 0.
Name: Date Type: SUB
Syntax: CALL Date(mo, day, yr, dow)
Return the current system date information. The day, month and
year can be immediately used in DFRMAT.
Copyright (C) InfoSoft, 1986-1990, 1991 11
Name: DayOfYr Type: FUNCTION
Syntax: DaySoFar = DayOfYr
This simply returns the day of year as an integer. It is
accurate for dates of 01-01-1980 to 02-28-2100 (The year 2100 is a
centennial skip leap year - every 400 years we skip a leap year).
This is a FUNCTION that works off the current system date, returning
the day count in the FUNCTION name. Example:
DECLARE FUNCTION DayOfYr%
.
.
TodayCount = DayOfYr
Name: DayOfWeek Type: FUNCTION
Syntax: DCode = DayOfWeek(month, day, yr)
DayOfWeek can also be called as ZellerDay.
This uses a modified form of Zeller's Congruence to determine the
day of week for any valid date. Example:
WeekDay = ZellerDay(5, 17, 1989) ' returns 3 for Wed
PRINT "That was a "; DayName$(WeekDay)
Name: Delay/Delay18 Type: SUB
Syntax: CALL Delay(secs)
CALL Delay18(ticks)
Delay will pause a given number of seconds to allow the user to
read a display that you may have sent to the screen. Delay18 allows a
delay resolution between that of Delay and MilliDelay by pausing in
increments of 1 clock tick or 1/18.2th of a second. Example:
sec=5
CALL Delay(sec) ' or CALL Delay(5)
..
CALL Delay18(9) ' 1/2 second
Name: DialogBox Type: SUB
Syntax: CALL DialogBox(Msg$, Prompt$, Ok$, Ret$) (DialogBox
is fully documented in MACRO17.DOC).
Copyright (C) InfoSoft, 1986-1990, 1991 12
Name: DFrmat Type: SUB (BASIC)
Syntax: CALL DFrmat(m, d, y, nudate$)
Passed integers for the date, this routine will pass back a
formatted date string. This is handy in formatting DOS/BASIC's
sterile date format into something that has a more pleasing on screen
appearance. The integers represent the day, month and year, and the
return is a string similar to "August 1, 1987".
DFRMAT has a lower range of 1800 as the year, and any year
passed that is lower than 1800 has 1900 added to it, making 87 as
valid an argument as 1987. Syntax:
CALL dfrmat(8, 1, 87, nudate$)
PRINT nudate$ ' output is August 1, 1987
Alternative:
CALL date(m, d, y, w)
CALL dfrmat(m, d, y, nudate$)
Name: DirA Type: FUNCTION
Syntax: errc = DirA(mask$, BYVAL VARPTR(fil$(1)))
DirA replicates the DOS DIR command in an elegant and efficient
method - no shelling, no reading the screen after a FILES statement
and no loops to execute numerous calls to get files and their names.
This is similar to the services provided by FirstF and NextF,
except that it places the returned file names directly into a string
array. If you need only a few names or are searching for a specific
name FirstF and NextF are ideal, but if you need to do something with
a file list, DirA is much faster and neater. DirA works conventional
string arrays (a Fixed Length String version is also included - see
DirFLS) - be sure to initialize each element to 12 or more spaces.
DirA returns just the file, not the pathname. If less than 12 spaces
are available, DirA will supply as much of the name as it can and
return a -1 to indicate you did not provide enough space in one or
more elements.
Since DirA works with a string array, you can use FilCnt first to
get the number of files matching the mask ("*.*", "*.bas" etc) so as
to dimension the array to the correct size. If the array is too small
for the number of matching files and is overrun, your program will
surely crash. (The array may be either Static or Dynamic).
Note: BASIC passes parameters to sub programs by passing it's
address. However when passing a string array element, it first makes
a copy of that element which makes it impossible to treat it as an
array element. By passing the first element of the array BYVAL, we
are able to pass the address of the actual starting point to fil in
the array. Because it is a FUNCTION and because it passes a parameter
BYVAL, DIRA MUST be declared.
Copyright (C) InfoSoft, 1986-1990, 1991 13
Example:
DECLARE FUNCTION DirA%(mask$, BYVAL ArryPtr%)
..
errc = FilCnt("*.*", count)
REDIM Fil$(count)
FOR x = 1 to count
Fil$(x) = SPACE$(12)
NEXT x
errc = DirA("*.*", VARPTR(Fil$(1)) )
Name: DirF Type: FUNCTION
Syntax: errc = DirF(mask$, SEG fil AS ANY)
Note: DirF may be invoked as either DirF or DirFLS
When you create a standard string array, what you actually create
is a table of string descriptors indicating the length and location of
each string element. A fixed length string array however is a con-
tiguous block of string memory with no descriptors. Further, QB
passes a standard string array IMAGE of a fixed length string array to
subprograms, so a bit of cleverness is needed to address a Fixed
Length string array - this is done by using the ANY keyword in the
declaration statement. According to Microsoft, the recommended way to
access User Defined (TYPE) structures and Fixed Length String Arrays
should be passed as a segmented address and as ANY (SEG xxx AS ANY).
Passing both the segment and address (VARSEG / VARPTR) BYVAL would
work because it is essentially the same thing, but this is certainly
messier.
In the case of DirFLS, we must use a fixed length string that is
precisely 12 characters per element. Using 13 or 11 or 15 will
scramble the names due to the contiguous nature of the memory block.
Further, since there are no descriptors associated with Fixed length
Strings, the only error DirF will be able to detect is a NULL mask.
Example:
DECLARE SUB DirF (mask$, SEG arryptr AS ANY)
..
..
TYPE FStruct ' struct to hide FLS array in
s AS STRING * 12
END TYPE
errc = FilCnt("*.*", count) ' count files
DIM fil(count) AS STRING * 12 ' make Fixed Len array
CALL DirF(mask$, fil(1)) ' get dir list
FOR x = 1 To count ' print them - note the .s
PRINT fil(x).s
NEXT x
Copyright (C) InfoSoft, 1986-1990, 1991 14
Name: DLight Type: FUNCTION
Syntax: errc = DLight(drive)
DLIGHT triggers the A: or B: drive light for the length of a 2
sector disk read. This is helpful in demo or training programs to add
realism to the session. It uses a BIOS level diskette service call
and will return a FUNCTION error of -1 if you attempt to invoke it on
a drive other than 0 or 1 (A: and B: respectively). On the other
hand, the drive light will come on even if the drive is open without
causing a "Drive Not Ready" error! Example:
DECLARE FUNCTION DLight%(drive%)
.
.
IF DLight(drv) THEN
PRINT "Hey, dummy - I said A: or B: !")
END IF
Name: DlrFrmat Type: FUNCTION (BASIC)
Syntax: errc = DlrFrmat(numstr$, mode, point)
This allows you to format a numeric string to various currency
conventions. Your options include allowing a "$" in front or not: if
you allow it, DLRFRMAT will check to see if it is there and add it if
it is not; if you do not want it, it will strip it off if entered.
You also are allowed to format it out to 2 or 3 decimals (tenths of a
cent). Parameters:
nst$=String containing only numbers, "." or "$" to be formatted.
Mode 0 - Returns numeric string without "$", forces a "." entry.
Mode 1 - Returns numeric string with "$", forces "." entry.
Point is used to tell DLRFRMAT how many decimals to pad to:
2 - pads "123." to "123.00"
3 - pads "45.1" to "45.100"
0 - automatic dollar decimal placement:
"5" becomes ".05", "70" becomes ".70" and "146"
becomes "1.46"
Example:
mode = 1 : DecPt=3
INPUT "Enter your wage: ",nst$ 'user keys '7.50'
CALL dlrfrmat(nst$, mode, DecPt)
wag$ = nst$
PRINT nst$ 'output: $7.500
Note that in the case of an error, errc will be set accordingly:
-1 = Invalid Mode specified
-2 = Null string passed
Copyright (C) InfoSoft, 1986-1990, 1991 15
Name: DosVer Type: FUNCTION
Syntax: OEM = DosVer(Major, Minor)
Returns the DOS Version the system is running under as well as the
OEM number, if any) - this is the DOS supplier for example, IBM's
PC-DOS will return 00 as the OEM number, DEC as 16h etc. The Major
and minor versions will be correct regardless of the OEM.
Name: DPRINT Type: SUB
Syntax: CALL DPRINT(a$)
CALL DPrint("Hello, World")
Beginning in QB4.00, the QB runtime library started to use a lower
level method of writing to the screen for normal PRINT statements.
This is good because it more or less builds in a QUICKPRINT feature to
the language. But it is bad if you wish to occasionally use ANSI or
other features that come with DOS level prints. DPRINT, is the
inverse of a QPRINT - it uses DOS to print to the screen so that ANSI
escape codes are recognized again. Another place that this is ex-
tremely helpful is when your application is running under a multitask-
ing system such as DoubleDOS, TaskView or similar - that is the
display output will not 'bleed' thru to the other side. DPRINT should
be declared so that you can syntactically use it the same as PRINT.
Example:
DECLARE SUB DPRINT(a$)
..
..
DPRINT CHR$(27) + "[2J" ' <Esc>[2J is ASNI code to CLS
DPRINT "Hello, world"
Copyright (C) InfoSoft, 1986-1990, 1991 16
Name: DrvError Type: FUNCTION
Syntax: errc = DrvError(drv$)
DrvError is a very powerful and important function providing for a
complete disk drive I/O Critical Error handler. It is called with the
string character of the drive to test ("A", "C" etc). It returns a
code indicating the level of readiness of that drive for I/O opera-
tions to allow you to completely forego ON ERROR to trap for open
drive doors, unformatted disks etc.
DrvError works on several levels: first it takes over the DOS
Critical Error Handler from BASIC - to trap errors before BASIC can.
Next, it treats drive B with special care, if you attempt DrvError on
"B", it will poll the system BIOS to see how many floppies are actual-
ly installed to avoid "Insert disk in Drive B:..." messages. Next,
DrvError tries to force an error first by reading the requested drive,
to test for drive door open, formatted disks etc. Then it attempts to
write to the drive by creating a unique file name, then deleting it.
In any test, if an error occurs, our Critical Error Handler ISR in
turn calls DOS to get the extended error information, tells DOS to
abort the operation, then uninstalls the Critical error ISR, and
returns the error code to you.
Possible DrvError Returns:
-1 = No Drive passed
-2 = Attempt on non existent "B"
0 = all is well - proceed with a light heart
11, 26 = possible format errors
15 = Bad drive (or path)
19 = Write Protect error
21 = Door Is open
29 = misc Read error
30 = Misc Write Error
31 = Not formatted
34 = Invalid change, (DNR)
59 = Critical error
See PhDrvSet and PhDrvCLr for suggestions on handling the phantom
drive flag. DrvError requires DOS 3.0 or greater
Example:
INPUT "Drive to use: ", drv$
errc = DrvError(drv$)
IF errc THEN
PRINT "Error reading from drive ";drv$
GOSUB DrvFailure
END IF
Copyright (C) InfoSoft, 1986-1990, 1991 17
Name: DrvSpace Type: SUB
Syntax: CALL DrvSpace(a, b, c, d)
Returns Total clusters, bytes per sector, available clusters, and
sectors per cluster for the specified drive, allowing you to determine
the overall drive space and/or free space.
Parameters:
Input:
a - drive number to poll, 1= A:, 2=B: etc; 0 = default.
Output:
a - Returns sectors per cluster
b - Returns available count of available clusters
c - Returns bytes per sector
d - Total clusters on drive
Example:
a=0 ' read default drive
CALL drvspace(a, b, c, d)
TotalSpace& = CLNG(a) * CLNG(c) * CLNG(d)
FreeSpace& = CLNG(a) * CLNG(c) * CLNG(b)
Name: EgaPrtScrn Type: SUB
Syntax: CALL EGAPrtScrn
Instructs the BIOS to ignore the default 25 line mode for Print-
-Screen operations and check for the correct display size. All future
Print-Screens (either via keyboard or GLIB's PrtScrn) will respect the
actual screen size.
Name: EqInfo Type: SUB
Syntax: CALL EqInfo(Ram, Ser, Par, Game, Floppy)
Returns some basic hardware configuration information. Extended
CPU information is returned by CPUInfo, and additional Video subsystem
is returned by VidInfo and VidType.
Parameters
RAM - Returns the amount of DOS memory installed
SER - Returns number of serial ports installed
PAR - Returns number of parallel ports installed
Game - Returns 0/1 for game port installed
Floppy- Returns 0,1,2 as number of physical floppies installed
Copyright (C) InfoSoft, 1986-1990, 1991 18
Name: ErrorMessage Type: SUB
Syntax: CALL ErrorMessage(msg$, row, attr, sfx)
ErrorMessage can also be invoked with the shorter name 'ErrMsg'
ErrorMessage is a complex and useful subprogram designed to flash
a defined message to the screen, pause 2 secs, then restore the
screen. It can be used for more than just error messages, but since
it restores the screen after the message display, it seems ideally
suited to error messages. You determine the line to use, the sub-
routine automatically centers the message.
Parameters:
msg$ = Message to display
row = Line for message to display on
attr = attribute to use
sfx = Sound effects. 0=none 1=low tone
Example:
msg$="You must enter a customer name!"
sfx=2
CALL errmsg(msg$, 15, 31, sfx)
Name: ExpandPath Type: SUB
Syntax: CALL ExpandPath(FilSpec$, FullName$)
DOS has an undocumented way of expanding filenames into fully
qualified path names, complete with drive designation. By passing
this routine a filename, it is expanded into a fully qualified file
spec. Note that this DOES NOT do a WHEREIS type function to find the
correct drive path designation, but merely appends the DEFAULT drive/
path spec to the name. This remains very handy for converting a
filespec in the current directory to a fully qualified name so that
you can change directories and then address that file by it's complete
name. The FullName$ where the qualified name is returned MUST be
initialized to 64 spaces. The routine will pad the return parameter
with spaces to 'blank out' any previous return.
Example:
DatFil$ = "myfil.dat"
fullname$ = SPACE$(64)
CALL ExpandPath(DatFil$, FullName$) ' expand
DatFil$ = LTRIM$(RTRIM$(FullName$)) ' store in old variable
CHDIR "\MAIN" ' move to main dir
' future references to DatFil$ will access the right file.
Copyright (C) InfoSoft, 1986-1990, 1991 19
Name: ExtPut/ExtGet Type: FUNCTION
Syntax: errc = ExtPut(SEG DBlock, EPage, Bytes)
errc = ExtGet(SEG DBlock, EPage, Bytes)
ExtPut and Extget allow your application to access and use
EXTENDED memory. This is NOT LIM/EMS memory but the memory found only
on 286 or 386 systems and usually associated with protected mode
operations. Such systems with more than 640k (usually 1MB) of onboard
memory will have EXTENDED memory and usually use it either as a print
spooler, ram disk or disk cache.
ExtPut and ExtGet allow you to actually store and retrieve data to
and from EXTENDED memory, which may add as much as 384k of such
'parking' memory to your larger programs. Note that the program does
not execute in EXTENDED memory, but will be able to use it for data
storage (usually an array). Once data from an array is moved there,
it can be erased or REDIMmed to hold something else, then later
resized and the data fetched back into DOS conventional memory for
your program to access once again. That is, data stored or 'parked'
in EXTENDED memory cannot be directly accessed by your program, but it
can be fetched back for access.
For purposes of these routines, we have broken the 384k (usually)
block of memory into 24 blocks of 16k of storage which will term as
PAGES. These pages or blocks are referenced as 0 thru 24. So, to
store data at the 1MB mark, EPage should be set to 0, to store data in
the second 16k block past the 1MB point, set EPage to 2 and so forth.
You may move more than 16k at a time, indeed up to 64k of data may be
moved in one call, but the 16k page size allows for maximum utiliz-
ation of extended memory with a minimum of waste.
ExtPut moves BYTES number of bytes from the passed array (DBLOCK) TO
extended memory into the 'parking' spot EMark * 16k above the 1 meg
mark. ExtGet, on the other hand fetches BYTES number of bytes from
the specified parking spot INTO DOS conventional memory specified by
DBLOCK. Even if you are not moving to or from an array, DBLOCK must
be passed as a SEG parameter. To pass more than 32k as the number of
bytes to move, use negative numbers for the BYTES parameter.
ExtPut and ExtGet are functions that return the following error
codes:
0 = Move went ok
1 = EXTENDED memory RAM parity error
2 = interrupt error
3 = gate address failed
A few notes on using Extended memory:
1) This should be considered a very advanced routine and
should NOT be utilized by you if you do not understand what
EXTENDED and EXPANDED memory are and how they differ.
2) Again, this is NOT EMS/EXPANDED memory.
Copyright (C) InfoSoft, 1986-1990, 1991 20
3) Moving less than 16k to or from EXTENDED memory still
utilizes the entire 16k page. That is, 8k cannot be
stored in the lower half of a block with the hopes of
storing another 5 to 8k in the upper half of that block.
This is designed this way to minimize extended memory
wastage and aid in managing what data is where: there
are generally only 24 blocks to keep track of. Note that
is it up to your program to manage the data and what is
stored where.
4) Unless you are using this in your application on your
machine, you have no assurances that EXTENDED memory is
not already in use as a spooler, ram disk or cache. To
check this, simply perform a few ExtGets of 16k on the
first few pages and if the entire array is NOT 0,
something else is using it and you should NOT store any
data anywhere in EXTENDED memory. Uninitialized EXTENDED
memory should always be ZEROES. If ANYTHING is using ANY
EXTENDED memory, you have no assurances that it might not
allocate more later and overwrite your data - or worse,
you could trash a VDisk with valuable data or wreck the
hard disk FAT by trashing an EXTENDED memory cache. To
determine whether a ExtGet is reading a cache, spooler or
VDisk or possibly reading old data stored there by a dif-
ferent application of yours, force a COLD BOOT at the end
of your application to clear all memory or store an ID
byte sequence at the start or end of the first block.
5) Use of this routine means that your program will NOT run
under OS/2 in the DOS compatibility box.
6) Some 8088 PC's, low quality clones in particular, may
crash and burn on this routine. So rather than depending
on the return from either Extget or ExtPut to determine
if it will work, use the GLIB functions CPUInfo and/or
ExtMem to determine system type.
7) Use of these functions requires that the CPU be placed
into protected mode, and may cause a loss of some
interrupts. For example, one or more characters MAY be
lost in programs that use ongoing serial communications
when either ExtPut or ExtGet are executed.
Copyright (C) InfoSoft, 1986-1990, 1991 21
Name: ExtMemFree Type: FUNCTION
Syntax: AtMem = ExtMemFree
Returns the amount of extended, or AT memory, that is installed in
a 286 based machine, but NOT allocated or in use. Many applications
that use extended memory now capture this interrupt and either return
0k of extended memory or that amount that is unallocated. Use of the
ExtPut and ExtGet DO NOT alter the number returned by this routine.
This only works on AT's or AT clones (80286 based machines).
mem = ExtMem
PRINT "AT/286 has ";mem;" of extended memory free."
Name: ExtMemInst Type: FUNCTION
Syntax: AtMem = ExtMemInst
Returns the amount of extended, or AT memory, that is installed in
a 286 based machine. This routine bypasses the interrupt that typi-
cally is captured to return a modified or zero extended memory value.
This returns the actual amount of extended memory installed and known
to the system. This only works on AT's or AT clones (80286 based
machines).
mem = ExtMemInst
PRINT "AT/286 has ";mem;" of extended memory installed."
Name: FADE Type: SUB
Syntax: CALL Fade
This is an interesting alternative to CLS. It quickly reads the
character at each location on the screen and decrements the ASCII
value of it until it reaches 32 (space). The attribute (color)
remains the same during and after the FADE. Because of the nature of
this effect, it must be done quickly and without the overhead of the
video retrace for CGAs. As a result this routine WILL cause snow on a
CGA and should only be used on MONO, EGA or VGA systems.
Name: FAttrGet Type: FUNCTION
Syntax: errc = FAttrGet(fil$, fattr)
Access to get the file attributes for a given file. Subsequent
calls to SetFattr (qv) allow you to set or reset a file attribute.
File attributes are as follows:
00 - Normal 04 - System
01 - Read Only 32 - Archive
02 - Hidden
The archive bit is usually used by back up programs to determine
if a file has been backed up since the last write process. To combine
attributes, just add the values, ie: Read Only - Hidden would be 3
because 1+2=3.
Copyright (C) InfoSoft, 1986-1990, 1991 22
This is a function and therefore also returns any error code in
the name of the function that can be evaluated itself, or assigned.
An error will result if the filename passed is not found (6). See
also FAttrSet. Error Codes:
-1 = Invalid File attribute
2 = File not found
3 = Path not found
5 = Access denied
Example:
DECLARE FUNCTION FAttrGet%(fil$, attrib%)
.
.
fil$ = "myfil.txt"
failure = FAttrGet(fil$, attrib)
IF failure THEN PRINT "Sorry, cannot find ";fil$
Name: FAttrSet Type: FUNCTION
Syntax: errc = FAttrSet(fil$, fattr)
FAttrSet allows you to change or modify the file attributes for
any disk file that exists. For a table of the attributes, see
FAttrGet. FattrSet is a function returning an error code. (DOS will
not allow changes to volume labels or directories via this function.)
Example:
DECLARE FUNCTION FAttrSet%(fil$, attrib%)
.
.
fil$="myprog.sys"
attrib=3 ' make it Read Only, Hidden
IF FAttrSet(fil$, attrib) THEN
PRINT "Error - possible invalid file attribute."
ELSE
PRINT "Change succeeded."
END IF
Name: FClose Type: FUNCTION
Syntax: errc = FClose(handle)
As expected, FCLOSE performs the opposite of FOPEN, close out a
file handle opened via FOPEN. FCLOSE does some positive error check-
ing to make sure that you do not attempt to close one of the standard
DOS file handles (like the keyboard, monitor etc) and will return a
error code of 6 - Invalid File handle.
See also FOpen FUnique, FCreat, FSetPtr, and DOS File Functions.
Example:
DECLARE FUNCTION FClose%(fhandle%)
.
.
result = fclose(fhandle)
IF result THEN GOSUB ErrorControl
Copyright (C) InfoSoft, 1986-1990, 1991 23
Name: FCopy Type: FUNCTION
Syntax: errc = FCopy(source$, dest$, buffer$)
This function copies a disk file using a buffer supplied by the
main program, to perform about as fast as the DOS COPY command. You
also pass it a source and destination string (paths / drives are ok).
The FUNCTION returns a variety of error conditions:
-1 = Null string passed as source or destination
2 = File Not Found
3 = Path not Found
4 = No Handle ("Too Many Files")
5 = Access Denied
Example:
DECLARE FUNCTION FCopy%(source$, dest$, buffer$)
.
.
result = fcopy("GLIB.ARC","\GOODSTUFF\GLIB.ARC", SPACE$(4096))
IF result THEN PRINT "Oops! Error - Check parameters!"
* Note the use of SPACE$ to supply the buffer. This automatically
creates a temporary buffer - upon the return from FCOPY, the buffer
memory is released.
Name: FCount Type: FUNCTION
Syntax: NumFiles = FCount(fil$)
FCount may also be invoked as FilCnt.
This is can be an indispensable tool - it quickly returns a count
of the number of files matching the given mask. This is extremely
useful in determining how large an array should prior to a Dir or
DirFLS call. If an invalid path or drive is included in the mask$, no
files will be found.
Name: FCreat Type: FUNCTION
Syntax: errc = FCreat(fil$, attrib, handle)
FCREAT is similar to FOPEN except that instead of opening an
existing file, we are CREATING a NEW file. As with FOPEN, and all the
DOS File Functions, error codes returned in the BASIC FUNCTION format
and are:
-1 Null string passed
3 Path not found
4 No handle available ("Too many files")
5 Access denied (this is returned when attempting to
FCreat a file that already exists - use FOpen in this case).
Note: You are encouraged to use FEXIST first to see if the file
already exists, executing FCREAT on an existing file truncates it to 0
bytes.
Copyright (C) InfoSoft, 1986-1990, 1991 24
Example:
DECLARE FUNCTION FCreat%(fil$, attrib%, fhandle%)
.
.
fil$="mainprg.sys": attrib=0
IF fcreat(fil$, attrib, fhandle)=0 THEN
PRINT "New file, ";fil$;" successfully created!"
ELSE
GOSUB WhatsGoingOn
END IF
Name: FDateGet/FDateSet Type: FUNCTION
Syntax: errc = FDateGet(handle%, mo%, day%, yr%)
errc = FDateSet(handle%, mo%, day%, yr%)
These allow you to SET or GET the date for a file for which you
have an open handle. (Use FOpen or BASIC's FILEATTR to get a handle).
You may set the file date for a handle, then continue to perform I/O
on that file and be assured that once closed, the file will be set
with the desired date. The only likely return code would be that the
handle% parameter is not a valid DOS handle. The year parameter may
be either 2 or 4 digits (ie 1989 or 89). Eg:
OPEN "foo.bar" FOR RANDOM AS #1
handle = FILEATTR(1,2)
errc = FDateSet(handle, 1, 1, 80) ' set date to 1/1/1980
Name: FDelete Type: FUNCTION
Syntax: errc = FDelete(fil$)
Simply deletes the file indicated by fil$ from the disk. The file
should NOT be open. This uses the DOS function UNLINK to simply
remove the first character so it may be UNDeleted with any of a number
of Disk tools. Example:
errc = FDelete("foo.bar")
Name: FDiskType Type: FUNCTION
Syntax: NumHDs = FDiskType(DrvNo, Cyl, Sectors, Heads)
Returns information regarding the installed fixed disk. On entry,
set DrvNo to the drive to poll (0 = first hard disk etc). The func-
tion returns the total number of fixed disks installed, and the
Cylinder, Sector and Head count of the drive requested. Example:
NumDrvs = FDiskType(0, Cyls, Secs, Hds)
Copyright (C) InfoSoft, 1986-1990, 1991 25
Name: FEOF Type: FUNCTION
Syntax: errc = FEOF(fhandle)
Sets the file pointer to the end of a file opened via FOPEN.
This actually sets the pointer to ONE BYTE less than the end of the
file. This is to be sure that subsequent FWRITE funtions overwrite
any hard EOF markers (ASCII 26) left by many text editors. FEOF also
checks for invalid handles as well as the 4 standard DOS handles and
aborts to return an error code of 6 - Invalid handle. Using FOPEN and
then FEOF is the equivalent of opening a file in APPEND mode using
BASIC's intrinsic file functions. See also: FSetPtr. Example:
DECLARE FUNCTION FEOF%(fhandle%)
.
IF FOpen("longtext.fil", 0, fhandle) THEN
GOSUB StartNewFile
ELSE
j= feof(fhandle)
IF j THEN GOSUB WeirdError
GOTO AppendToText
END IF
Name: FExists Type: FUNCTION
Syntax: ExistCode = FExists(fil$)
This may also be called as FileExists
Sets the return code (non zero) if the given file exists and no
path or other error is encountered. See also FileDNE.
Example:
DECLARE FUNCTION FExists%(fil$)
..
fil$ = "foo.bar"
IF FExists(fil$) THEN
PRINT fil$;" already exists! Overwrite?"
END IF
Name: FFlush Type: FUNCTION
Syntax: errc= FFlush(Fhandle)
FFlush will dump any buffered data to disk much faster than
closing and then reopening the file will. FFlush will NOT dump the
buffer for files opened using QB functions - QB does some significant
buffering of its own that does not respond to FFlush. Pass FFlush the
handle associated with the file, any return indicates an error code
the same as the other DOS file functions. Example:
errc = FFlush(fhandle)
Name: FFlushAll Type: SUB
Syntax: CALL FFlushA
Flushes all DOS file buffers to disk and updates disk directories.
This will not update the directories of files that are currently open.
This is in contrast to FFlush that both commits a file to disk and
updates the disk directory for a specific open file handle.
Copyright (C) InfoSoft, 1986-1990, 1991 26
Name: FHFree Type: FUNCTION
Syntax: FreeH = FHFree%
Returns an integer representing the number of file handles free or
unallocated or available. See also FHMax, FHUsed.
Name: FHMax Type: FUNCTION
Syntax: MaxH = FHMax%
Returns the number of maximum file handles available to the
system. DOS by default allows 20 handles, but more or less can be
available by using the FILES command in CONFIG.SYS. FHMax returns the
number configured by CONFIG.SYS. See also FHFree and FHUsed.
Name: FHUsed Type: FUNCTION
Syntax: HUsed = FHUsed
Returns the number of file handles in use by the system or other
processes. By default, DOS will use several handles for the standard
devices (stdaux, stdprn, stderr, stdout and stdin), and others may be
in use by TSR's, or other processes. Note that FHMax less FHUsed will
equal FHFree. See also FHFree, FHMax.
Name: FileDNE Type: FUNCTION
Syntax: errc = FileDNE(fil$)
This may also be called as FNotFound
This provides the inverse to the logic found in FExists. Instead
of testing if a file DOES exist, it returns non zero if the file DOES
NOT exist. This can be handy for logic or statements that work better
with the non zero return. See also FExists. Example:
'REM Instead of:
IF NOT FExists(Fil$) or IF FExists(fil$) = 0
IF FileDNE(fil$) THEN
PRINT "File Does Not Exist."
END IF
Name: FInfo Type: FUNCTION
Syntax: errc = FInfo(FilMask$, SEG FileInfo AS structf)
Returns compleat information about the file specified by FilMask$.
The information is returned in a user defined data structure (TYPE)
that is as follows (feel free to change names, but NOT the order!):
Copyright (C) InfoSoft, 1986-1990, 1991 27
TYPE structf
FilAttr AS INTEGER ; the file attribute
FilHour AS INTEGER ; the file time Hour
FilMin AS INTEGER ; the file time Minute
FilSec AS INTEGER ; the file time Seconds
FilMon AS INTEGER ; the file date Month
FilDay AS INTEGER ; the file date Day
FilYr AS INTEGER ; the file date Year
FilSiz AS LONG ; the size (in bytes) of the file
FilSpec AS STRING * 12 ; the file name (no wildcards)
END TYPE
DIM FilInfo AS Structf
errc = FInfo("*.exe", FilInfo)
PRINT USING "Name: & Size: ########";FilInfo.FilSpec;_
FilInfo.FilSiz
errc returns any error condition found by FInfo:
-1 = File not found (check the path)
-3 = Mask error (FMask$ may be "")
The biggest use for this function is to fetch more compleat
information on a known file. While using wildcards are OK, only the
first file matching the mask is returned, ie there is no FindNextFInfo
routine. Once your program is sure of the location (path) and name
use FInfo to fetch the rest of the name or use FInfoA (see also).
Name: FInfoA Type: FUNCTION
Syntax: errc = FInfoA(FilMask$, SEG FileInfo() AS structf)
This works identically to Finfo except that it fetches the file
information into a user defined data structure ARRAY. Useful when you
need complete information on all .EXE files, or all .DAT files. The
TYPE structure is identical to that in FInfo (see also). Wildcards
are advisable and BE SURE to dimension the array large enough to hold
all the files that will may found:
fmask$ = "*.dat" ' fetch data files
QFiles = FCount(fmask$) ' (qv) count number of files
REDIM FilInfo(QFiles) AS Structf ' large enough and right type
errc = FinfoA(FMask$, FilInfo(1))
FOR x = 1 TO QFiles
' print name and size
PRINT FilInfo(x).FilSpec; FilInfo(x).FilSiz
NEXT x
Name: FlexMenu Type: FUNCTION
Syntax: item = MenuChoice% (Menu$(), Trow%, LCol%, Nattr%,_
Hattr%, Title$, Mark%(), XtdChc%)
Extensive Menuing function fully documented in MACROxx.DOC.
Copyright (C) InfoSoft, 1986-1990, 1991 28
Name: FindFirst Type: FUNCTION
Syntax: errc = FindFirst(mask$, ret$)
FindFirst may also be called as FileFirst
This provides a simple, easy and straight forward access to disk
directories by seeking the first file matching the given mask. Things
such as an invalid path or drive will force an error return. If errc
is clear (zero), then ret$ will hold the name of the first file found.
Since FirstF is in assembler, you must initialize ret$ to 12 spaces to
hold the returned name (Fewer than 12 spaces, and FirstF will provide
as many characters as possible, and set the Error Flag - but no way,
no how will your error result in String Space Corrupt errors with
GLIB!). Use FindNext to get subsequent matching files. FindFirst can
be used as a form of finding out if a file exists and even if a path
is valid or not. Example:
DECLARE FUNCTION FindFirst%(mask$, retf$)
..
retf$ = SPACE$(12)
mask$ = "\BIN\UTILITIES\*.COM" ' try for list of COM files
' in \BIN\UTILITIES dir
errc = FindFirst(mask$, ret$)
IF errc THEN
.. something is wrong: path, none found etc
ELSE
... retf$ holds filename of first \BIN\UTILITES\COM 'files
END IF
Name: FindNext Type: FUNCTION
Syntax: errc = FindNext(ret$)
FindNext may also be called as FileNext
This returns subsequent filenames matching the mask passed in
FindFirst. The mask need not be passed again, but ret$ must be
initialized to 12 or more spaces. Once a successful FindFirst is
executed, the only likely error return in errc is 18 that signals "no
files found". Example: (more code intensive than DirA or DIRFLS)
DECLARE FUNCTION FindFirst%(mask$, retf$)
DECLARE FUNCTION FindNext%(ret$)
..
retf$ = SPACE$(12)
mask$ = "\BIN\UTILITIES\*.COM" ' look thru COM files
' in \BIN\UTILITIES dir
errc = FindFirst(mask$, ret$)
IF errc THEN
.. something is wrong: path, none found etc
ELSE
DO
ret$ = SPACE$(12)
errc = FindNext(ret$)
LOOP UNTIL (errc=18) or ( INSTR(ret$, "FOOBAR.COM") )
' loop until no more file found, or a specific file is found
END IF
Copyright (C) InfoSoft, 1986-1990, 1991 29
Name: FlexType Type: FUNCTION
Syntax: FlexCode = FlexType(drv, NumFlex)
Returns the number of installed flex disk drives ("floppies") and
a type code for the specified drive. NumFlex returns with the actual,
physical number of flex drives installed, FlexCode returns a code
identifying the type of flex DRIVE (NOT flex DISK!) installed:
-1 = Invalid drive requested
00 = Unknown drive type or function not supported (See note)
01 = 360k 5.25"
02 = 1.2MB 5.25"
03 = 720k 3.5"
04 = 1.4MB 3.5"
Note: Older 8088 PC BIOSes, do not support this function, and
return -1 noting this; cheaper clones may even lock up, so invoke this
on 8088 systems at your own risk (A PC most likely has a 360k drive).
Name: FMove Type: FUNCTION
Syntax: errc = FMove(source$, dest$, buffer$)
This works the same as a FCopy/FDelete combination with source
file being deleted after the destination file is created. As with
FCopy and FPrint, you supply the buffer by simply passing a string or
temporary variable. Any errc return indicates an error such as disk
full, file already exists and is Read Only, or disk is write protect-
ed. The source and destination file name may be on different devices.
Example:
errc = FMove("foo.bar", "A:foo.bak", SPACE$(4096))
Name: FOpen Type: FUNCTION
Syntax: errc = FOpen(fil$, mode, fhandle)
FOPEN is a standard DOS function to open a file via a file
handle. FOPEN requires a 'mode' be passed, 1 = multitasking or
networking, 0 = normal. There is a way to set access rights (read,
write, read/write) that also may be implemented later. DOS even
reserves a special handle for your printer (see: "Dos File Functions")
In order to keep the number of parameters down, the fhandle parameter
is used to pass back the file handle and FOPEN is designed as a
FUNCTION in assembler to return any error codes the same as a FUNCTION
operates in BASIC.
An error can occur if the file handle is invalid, the file is already
open, file not found etc. In this case, the errorcode or result will
indicate what happened and any fhandle number should be ignored.
Example:
DECLARE FUNCTION FOpen%(fil$, mode%, fhandle%)
..
fil$="myprog.dat" : mode=0
IF fopen(fil$, mode, fhandle) THEN
GOSUB FileError
ELSE
PRINT fil$;" opened with a handle of ";fhandle
END IF
Copyright (C) InfoSoft, 1986-1990, 1991 30
Name: FPrint Type: SUB
Syntax: CALL FPrint(doc$, buffer$)
Send a file from disk to the first printer (LPT1, PRN etc).
This is a much handier way to print a file rather than reading it line
by line and LPRINTing it, and takes as much memory as you lend it by
way of the buffer. Regardless, it takes less memory than to SHELL to
DOS and copy it to the printer and is faster than to LINE INPUT each
line and LPRINT it. This routine will not abort if the printer is
not ready, test for printer readiness with PtrStat. Example:
printfil$="GLIB16.DOC"
CALL FPrint(printfil$, SPACE$(4096))
Name: FReadArray Type: FUNCTION
Syntax: errc = FReadArray(SEG arry, Fhandle, BYTES)
FReadArray reads data from a disk file directly into an array.
The file must have a valid DOS File Handle which is accomplished
either by using FOpen or FILEATTR on a BASIC file number. Elements
indicates the number of BYTES to fill (remember that each elements in
the array is 2 Bytes), upon return from the function BYTES is reset to
the actual number read (in case EOF is encountered before all the
requested bytes can be read). ERRC is set to indicate any DOS error
encountered. See the complimentary function FWriteArry; GLIBDEMO
shows a practical use - binary screen libraries.
Example:
DECLARE FUNCTION FReadArry%(SEG arry%, Fhandle%, Bytes%)
..
..
REDIM ScrnArry(2000) ' 2000 elements = 1 screen
fil = FREEFILE ' get next BAS file no
OPEN "screens" FOR OUTPUT AS #fil
handle = FILEATTR(fil,2)
Bytes = 4000 ' 2000 * 2
errc = FreadArray(ScrnArry(1), handle, Bytes)
Name:FReadByte/FWriteByte Type: FUNCTION
Syntax: errc = FReadByte(handle, byte)
errc = FWriteByte(handle, byte)
This is similar to BASIC native BINARY file I/O, allow single byte
file access. This is not a character but a byte, or the ASCII value
of the byte ( ASC(ch$) ) to be sent or read from disk.
You must have a valid, open handle for the destination file - use
FOpen or BASIC's FILEATTR for this. This can be considerably quicker
for byte I/O than BASIC's BINARY method of allocating a string, then
GETting and so forth. Example Read 5 bytes:
FOR x = 1 TO 5
errc = FReadByte(handle, byte)
PRINT "Byte #";x;" is: "; byte
NEXT x
Copyright (C) InfoSoft, 1986-1990, 1991 31
Name: FReadStr Type: FUNCTION
Syntax: errc = FReadStr(Thing$, Fhandle, chars)
FReadStr reads data from a disk file directly into a string
variable. The file must have a valid DOS File Handle which is ac-
complished either by using FOpen or FILEATTR on a BASIC file number.
Elements indicates the number of CHARACTERS or BYTES to read, upon
return from the function, CHARS is reset to the actual number read (in
case EOF is encountered before all the requested characters can be
read). ERRC is set to indicate any DOS error encountered. Because
FReadStr is in high-speed assembler, you must initialize the buffer or
string that will hold the read data to at least as long as the number
of characters to read or an error will occur. See the complimentary
function FReadStr.
Example:
DECLARE FUNCTION FReadStr%(Buffer$, Fhandle%, Bytes%)
..
..
message$ = SPACE$(25)
chars = 25
fil = FREEFILE ' get next BAS file no
OPEN "screens" FOR OUTPUT AS #fil
handle = FILEATTR(fil,2)
errc = FReadStr(Message$, handle, chars)
Name: FRecGet/FRecPut Type: FUNCTION
Syntax: errc = FRecGet(handle, size, SEG struct)
errc = FRecPut(handle, size, SEG struct)
These perform essentially the same function as QB's GET # and PUT
# by reading a single record from the current location of the file
pointer represented by the handle passed. Use FsetPtr (qv) to set the
file pointer to the desired location. These are the single record
version of FRecGetA/FRecPutA (qv). In using these over PUT/GET, you
can completely bypass QB's file I/O, buffering and obnoxious error
routines and interpret the return code for errors. The biggest ad-
vantage to using these will be to those who are also using the multi-
ple record I/O routines (FGet/PutRecA). Note that while these are
setup for TYPEd file I/O, they will work for FIELDed files, though the
hassle involved with this is probably not worth the effort. An error
return indicates failure, generally an invalid handle was passed (6).
See also FGetRecA/FSetRecA, FSetPtr. See MFEDDEMO.BAS for examples.
Copyright (C) InfoSoft, 1986-1990, 1991 32
Name: FRecGetA/FRecPutA Type: FUNCTION
Syntax: errc = FRecGetA(handle, Quan, size, SEG struct)
errc = FRecPutA(handle, Quan, size, SEG struct)
These perform essentially the same function as QB's GET# and PUT#
but rather than reading a single record, they will fill a TYPE array
with the number of records designated by Quan. That is, rather than
reading (or writing) many records from within a QB FOR...NEXT loop,
you can read as many as desired in one pass and much quicker, making
it ideal for large database operations:
errc = FGetRec(handle, 128, LEN(Emp(1)), Emp(1))
This would read 128 records from the file handle (starting at the
current location) and place them in the TYPE array Emp beginning at
subscript 1. The size of the (TYPE) structure is passed so that the
functions can calculate the number of bytes to read.
At this point, care must be taken that the read or write (trans-
fer) request does not exceed 64k (Quan recs times Size of struct). On
the low end that means a max of 65536 1 bytes records or 32,768 2 byte
records which is pretty reasonable. On the high end, with large
structures, you will need to make multiple 64k passes so the data is
read from (or written to) the correct memory segment (large type
structures straddle or cross segment boundaries). Example:
' assume LEN(RecStruct) = 512 bytes, and we want to read 256 '
of them to fill a 128k array:
' read 64k (128 * 512) to RecStruct(1)
errc = FGetRec(handle, 128, LEN(RecStruct(1)), RecStruct(1))
' read next 64k to RecStruct(129)
errc = FGetRec(handle, 128, LEN(RecStruct(1)), RecStruct(129))
Note that RecStruct subscripts would be 0 and 128 under OPTION BASE 0.
The point is that even though it is one array, the destination
segment for RecStruct(1) is different from that of ResStruct(129)
(though they have adjacent addresses). Should you attempt this:
' try to read 128k (256 * 512 struct size)
errc = FGetRec(handle, 256, LEN(RecStruct(1)), RecStruct(1))
the routine would indeed read 128k but the last 64k would overwrite
the first 64k ie: records 128 to 256 would be stored at RecStruct(1)
to RecStruct (128). We plan to modify this in the future to properly
recognize the end of a segment so that more than 64k can be read in
one call.
The only likely return code placed in errc, generally signals an
invalid handle (6) or a SHARE violation (5).
NOTE: Records or data are read from the file at the current DOS
file pointer position. Use FSetPtr to locate this to the desired
spot: QB's SEEK may not always do the equivalent on random files.
See also FGetRecA/FSetRecA, FSetPtr. See MFEDDEMO.BAS for examples.
Copyright (C) InfoSoft, 1986-1990, 1991 33
Name: FRename Type: FUNCTION
Syntax: errc = FRename(oldf$, newf$)
This allow you to rename a disk file. Since a simple DOS function
is used, both the source and destination files must reside on the same
device (you may not move the file from one drive to another with this
function - see FMove, FReplicate or FCopy for that). Any return
indicates an error such as an attempt to span drives. Example:
errc = FRename("foobar.new", "foobar.old")
Name: FReplicate Type: FUNCTION
Syntax: errc = FReplicate(source$, dest$, buffer$)
This works very similarly to FCopy, except the file date and time
are preserved on the destination file. As with FCopy and Fprint, you
supply the buffer by simply passing a string or temporary variable.
Any errc return indicates an error such as disk full, file already
exists and is Read Only, or disk is write protected. Eg:
errc = FReplicate("foo.bar", "A:foo.bak", SPACE$(4096))
Name: FSetPtr Type: FUNCTION
Syntax: errc = FSetPtr(Fhandle, RecNo&, RecSize)
Moves the DOS file pointer to a specified location in a file
(usually to a specific record in a random file) opened with a handle.
Note that RecNo is a LONG INTEGER so that very large files can be
addressed. This function is used with FGetRec, FPutRec, FGetRecA and
FPutRecA (qv) to locate the DOS file pointer to a specific location.
Note that this acts directly on the DOS file pointer and therefore
acts differently than QB's native SEEK would (due to significant file
buffering performed by the QB RTL itself). The use of this function
is a prerequisite to calls to FGetRec, FPutRec, FGetRecA and FPutRecA.
See also FEOF, FRecGet, FRecPut, FRecGetA, FRecPutA.
Example: (TYPE Method)
TYPE struct
AName AS STRING * 25
BStuff AS STRING * 15
FooBar$ AS STRING * 15
END TYPE
DIM RecThing AS STRUCT
RSIZE = LEN(RecThing) ' do 1ce rather than many LEN calls
OPEN datfil$ for RANDOM as #f LEN = RSize
Fhandle = FILEATTR(f, 2) ' Ask BASIC for handle of file
..
..
errc = FSetPtr(FHandle, RecNo&, RSize) ' seek to RecNo
Copyright (C) InfoSoft, 1986-1990, 1991 34
Name: FTimeClear Type: FUNCTION
Syntax: errc = FTimeClear(fhandle)
This allows you to 'clear' a file time so that the time will not
display when using the DOS DIR command. The handle must be a valid,
open handle using either FOpen or BASIC's OPEN and FILEATTR. Example:
fhandle = FILEATTR(BasNo, 2)
errc = FTimeClear(fhandle)
Name: FTimeGet/FTimeSet Type: FUNCTION
Syntax: errc = FTimeGet(fhandle, hour, min, sec)
errc = FTimeSet(fhandle, hour, min, sec)
Like the name implies, these allow you to set or get the time of a
file - actually the last time it's directory entry was updated. You
must have a valid, open handle for the file via FOpen or BASIC's
FILEATTR function. All parameters must be integers and the only
likely error code is if the handle is not valid (file is closed). If
you perform I/O on a file AFTER setting the time, that time request is
used when the directory entry is updated when the file is closed. See
also FTimeClear. Example:
handle = FILEATTR(BasNo, 2)
errc = FTimeSet(handle, 10, 10, 10) ' set time to "10:10:10"
Name: FuncResp Type: FUNCTION
Syntax: RetCode = FuncResp
Returns an integer representing a function key press. The routine
does not return until one is pressed.
1 - 10 = F1 to 10
11 - 20 = Shift + F1 to 10
21 - 30 = Alt + F1 to 10
31 - 40 = Control + F1 to 10
Copyright (C) InfoSoft, 1986-1990, 1991 35
Name: FUnique Type: FUNCTION
Syntax: errx = FUnique(fil$, attr, fhandle)
This may also be invoked as FUniq
This DOS disk file function creates a file with a unique name,
which makes it ideal for scratch data files. Rather than HOPING that
"mydat.@@@" is a unique filename, FUNIQUE makes SURE that a file is in
fact unique. DOS will create such a file in the specified directory
and open it with read write access with the attributes you specify.
Furthermore, FUNIQUE can, at your option, return the actual
file NAME as well as the handle. Enter the call with a string con-
taining the desired drive and path where you want the unique file
created, BE SURE to include a trailing backslash ("\")! FUNIQ will
return a file handle or error code, and if you add 12 trailing spaces
to the pathname, it will return the filename. More often than not,
the unique name will be just 8 chars long, but if not, it would only
return part of the name. When the unique name IS less than 12 char-
acters the name will be padded with spaces which allows you to use
BASIC's native RTRIM$ to fix it.
NOTE: The unique file is OPEN with a handle! Subsequent file
access should be thru FWriteArray or FReadArray, or FCLOSE the handle,
reopen the filename with BASIC's OPEN so as to access the filename via
BASIC functions.
NOTE: Use of FUNIQUE requires DOS 3.0 or greater.
Example:
DECLARE FUNCTION FUnique%(fil$, attrib%, fhandle%)
..
..
tempfil$="C:\BIN\ "
IF FUnique(fil$, 0, fhandle) THEN ' path, normal file
GOSUB InvalidInfo
ELSE
j=fclose(fhandle) ' close the handle
tnum=FREEFILE ' get BASIC handle
OPEN tempfil$ FOR APPEND AS #tnum ' reopen file in
END IF ' BASIC mode
Copyright (C) InfoSoft, 1986-1990, 1991 36
Name: FWriteArry Type: FUNCTION
Syntax: errc = FWriteArry(SEG arry%, Fhandle%, BYTES%)
FWriteArray writes data from an array directly to a disk file.
The file must have a valid DOS File Handle which is accomplished
either by using FOpen or FILEATTR on a BASIC file number. 'Chars'
indicates the number of BYTES to write (remember that each elements in
the array is 2 Bytes), upon return from the function BYTES is reset to
the actual number written (in case of a lack of diskspace, or invalid
handle, the number written will be less than that requested). ERRC
is set to indicate any DOS error encountered. See the complimentary
function FReadArry; GLIBDEMO shows a practical use - binary screen
libs. Example:
DECLARE SUB SvScrn(SEG Arry%)
DECLARE FUNCTION FWriteArry%(SEG arry%, Fhandle%, Bytes%)
..
..
REDIM ScrnArry(2000)
CALL SvScrn(ScrnArry(1)) ' save screen to array
fil = FREEFILE ' get next BAS file no
OPEN "screens" FOR OUTPUT AS #fil
handle = FILEATTR(fil,2)
count = 4000 ' 4000 bytes in 2000 elements
errc = FWriteArry(ScrnArry(1), handle, count)
Name: FWriteStr Type: FUNCTION
Syntax: errc = FWriteStr(SEG arry, Fhandle, Chars)
FWriteStr writes data from a string buffer directly to a disk
file. The file must have a valid DOS File Handle which is accomplish-
ed either by using FOpen or FILEATTR on a BASIC file number. 'Chars'
indicates the number of characters to write, upon return from the
function Chars is reset to the actual number written (in case of a
lack of diskspace, or invalid handle, the number written will be less
than that requested). ERRC is set to indicate any DOS error en-
countered. See the complimentary function FReadStr. Example:
DECLARE FUNCTION FWriteStr%(Buffer$, Fhandle%, chars%)
..
..
LINE INPUT "Your name, age and occupation: ", info$
fil = FREEFILE ' get next BAS file no
OPEN fil$ FOR OUTPUT AS #fil
handle = FILEATTR(fil,2) ' convert File No to handle
count = LEN(info$) ' get number to write
errc = FWriteStr(info$, handle, count)
Copyright (C) InfoSoft, 1986-1990, 1991 37
Name: GetCmdTail Type: FUNCTION
Syntax: errc = GetCmdTail(tail$)
Fetches the unparsed command tail from the PSP (Program Segment
Prefix). Unlike BASIC's COMMAND$, this is not converted to uppercase
or otherwise touched: it is exactly as the user typed it, allowing
your program to act on case sensitive switches. Initialize tail$ to
128 spaces or use GetCmdTLen (qv) to determine the size of the command
tail. Note that using this under the QB environment will return the
command line to invoke QB, use QBLoaded (qv) to determine how to
interpret the tail$ return. The return code indicates possible error
conditions: -1 = String too short: there is not enough room to store
the entire command tail in the string. In this case, GetCmdTail
returns as much as it can, and sets the error code. See GetCmdTLen
Name: GetCmdStr Type: FUNCTION
Syntax: CmdStr$ = GetCmdStr$
This is a hybrid of GetCmdTail and ArgVar$ wherein the function
returns the unparsed command tail (like GetCmdTail) and returns it as
a function (like ArgVar). This will most likely replace GetCmdTail in
a future version. Example:
CmdLine$ = GetCmdStr$
Name: GetCmdTLen Type: FUNCTION
Syntax: TailSize = GetCmdTLen
Returns the string length required to store the command tail.
Allows you to initialize a string to the right length prior to a call
to GetCmdTail rather than assuming 128 and then trimming it. The
return is either the length required or -3 indicating incorrect DOS
version (GetCmdTLen requires DOS 3.0).
Example: (assume we checked DOS Version already)
size = GetCmdTLen ' get size required
SELECT CASE size
CASE 0 ' no command line passed
PRINT "No Command Line !"
CLOSE
SYSTEM
CASE IS > 0
tail$ = SPACE$(size) ' initilize space
errc = GetCmdTail(tail$) ' get tail
IF QBLoaded THEN ' test if running under
' the QB env
GOSUB AjustTail ' adjust the return
END IF
GOSUB ParseArgs ' get options
CASE ELSE
PRINT "Weird error"
SYSTEM
END SELECT
Copyright (C) InfoSoft, 1986-1990, 1991 38
Name: GetCH Type: FUNCTION
Syntax: ret$ = GetCH$(okay$)
Return keystroke from allowable string of selections. Pass
this routine a string of okay characters (in upper case) it will
return which of those were pressed. GETCH ignores input other than
those characters in the okay$. If passed a null GETCH string or a
null return string, GetCh will return the first key pressed. Addi-
tionally, 2 features found in GETCH not in other routines of this
nature, is that it will not get confused by any ANSI keyboard redefin-
itions and when used on a network, will not hang the terminal or
server when called. Note: GetCh purges the type ahead buffer first.
See also PGetCH, DialogBox. Example:
PRINT "Are You Sure?": ky$=" "
CALL getch("YN", ky$) ' allows input of Y or N only
Name: GetDrv Type: FUNCTION
Syntax: drv = GetDrv
This gets the default disk drive. It returns the ASCII code of
the letter to avoid the confusion of drive numbering. Converting to a
character is simple with BASIC's CHR$ function.
Name: GetDSeg Type: FUNCTION
Syntax: DS = GetDSeg
This is more a development utility than a usable subroutine.
This returns BASIC's default Data Segment (DS). In tinkering with
calling C and routines from other languages, I've found this useful in
making sure that the default data segment is not changed.
Name: GetStack Type: FUNCTION
Syntax: SP = GetStack
Returns the state of BASIC's stack. This is very helpful in
determining what (if any) the stack should be set to, via a
'CLEAR,,xxxx' statement at the start of your program. The stack grows
DOWNWARD with each successive GOSUB, so at strategic points in your
code, calling GETSTACK and comparing it to the state of the STACK at
the start of the program, aids in determining if you do need to
include a stack statement at the start.
Name: HALT Type: SUB
Syntax: CALL HALT
Stops the system cold, requiring it to be shut off. This can be
handy in security situations or when you want to be sure that memory
is cleared after your program is run. This is similar to ShutDown
except that there is no disk parking and no graphics.
Copyright (C) InfoSoft, 1986-1990, 1991 39
Name: IACRead/IACSet/IACClear Type: FUNCTION
Syntax: errc = IACRead(s$, iopt)
errc = IACSet(s$, iopt)
errc = IACClear
Your machine's BIOS reserves a small amount of room (very small)
in low memory specifically for Inter Application Communications ie to
pass data between each other. This area is limited to 16 bytes, but
this is enough to pass or store a 12 character filename and up to 2
integer variables. The problem is that if you store a filename or
string here for a later program, and before it can be read, another
program uses this area first, our info is lost (though very few
programs use this). While a boot obviously destroys anything stored
in the IAC, we have stored things there and found them to be intact at
the end of the day.
To detect any corruption of the IAC area, we will use 2 bytes of
the space to store a 16 bit checksum. When reading data from the IAC
area if the checksum does not match, an error code of -3 is returned.
IACSet: errc = IACSet("string var", mopt)
Saves the string variable indicated as well as the
integer value to the IAC area.
The string variable may be of any length up to 12 characters, but
not more than that. If the string passed is larger than 12 char-
acters, the process is not carried out and an error code of -1 is
returned. This allows at least a complete filename to be stored or a
decent size string.
IACRead: errc = ReadIAC(stringvar$, intvar)
Reads the Intra-Application Communications Area, and stores the
first 12 bytes into the string variable, and fills the integer var-
iable with any value previously saved to the ICA area. If a string of
less than 12 spaces is passed, nothing is returned and an error code
of -2 is returned.
IACClear CALL IACCLear
This unambiguously overwrites the string area of the IAC with
spaces and the integer area with zeroes and resets the checksum.
Copyright (C) InfoSoft, 1986-1990, 1991 40
Name: INCR / DECR Type: FUNCTION
Syntax: result = INCR(x, y)
result = DECR(x, y)
There are people out there who made the tragic mistake of
getting into one of those "other" BASIC dialects, and are having
trouble adapting to QB. INCR and DECR are meant to help alleviate
this. If DECLARED as a SUB, they will work just like Turbo BASIC's
native functions of the same name.
Name: InsOn / InsOff Type: FUNCTION
Syntax: CALL InsOn : CALL InsOff
This subroutine, simple puts the keyboard into INSERT ON state
(INSON) or turns the insert toggle off (INSOFF). Example:
CALL InsOn
CALL InsOff
Name: INSTRI Type: FUNCTION
Syntax: result = INSTRI(Start, FindIn$, LookFor$)
This function is identical to the BASIC native INSTR except that
it is case insensitive. That is, INSTRI will return an integer
pointing to the first occurrence of either "CD" or "cd" in "ABCDEF" or
"abcdef". Like INSTR, INSTRI allows the use of a starting point to
begin the search within the string to BE searched, unlike BASIC, this
is not optional, a 0 will point to the same starting point. Like
BASIC, the return is a relative pointer from the starting point.
Further, the routine will recognize "?" in the search string as a
match-all wild card. Example:
DECLARE FUNCTION INSTRI%(start%, a$, b$)
..
PRINT INSTRI(1, "AbCdEFGhiJkL", "cDe?") ' prints 3
Name(s): ISxxxxxx Type: FUNCTION(s)
Syntax: status = IsXxxxx(c$)
The 'izzy' collection provides for assembler level replication of
the highly useful IS??????? macros found in 'C'. Where the 'C' macros
work only on a single character, the InfoSoft assembler implementation
works on either a character or a string. When using a string however,
a single non matching character forces a false return. Example:
IF IsAlpha("The quick brown fox is really a lazy dog.") THEN
PRINT "All Alpha chars!"
ELSE
PRINT "Non alpha chars in string!"
END IF
In this example, the return is FALSE, the string is NOT all alpha
characters - the spaces and period in the string cause a zero (FALSE)
return. All the IZZY functions return a 0 or -1 based on the func-
tion. The IZZY functions are:
Copyright (C) InfoSoft, 1986-1990, 1991 41
IsASCII - Test if the string or character passed is
> 0 and < 128 or ASCII
IsAlpha - Test if the string or character is between A-Z or
a-z.
IsAlNum - Test if the character or string is made of
characters A-Z, a-z or 0-9.
IsCntrl - Test if the string or character is in the range 0
to 31 or 127.
IsDigit - Test if the character or string is a decimal digit,
(0-9).
IsGraph - Test if the string or character is a printable.
The space is not considered a printable character.
In general, this means the characters ASCII 33 to
127.
IsPrint - Same as IsGraph except the space is allowed: ASCII
32 to 127
IsPunct - Tests for whether a string or character is a
punctuation mark: ~!@#$%^&*(){}[]:;"'?/><.,
IsSpace - Test a character or string to see if it is a
whitespace character (ASCII 9 to 13 or 32).
IsUpper - Tests to see if the string or character is Upper
case. Very useful when you want to preserve the
case of some input or want to avoid generating
string garbage in reassigning UCASE(x$) to a new,
temporary variable.
IsLower - Similar to IsUpper - tests for lower case.
IsxDigit - Test for a string or character is a hex digit.
0-9, A-F and a-f are valid hexadecimal digits.
IsGrafx - Tests if a string or character is a graphic box type
character. These are ASCII 176 to 223.
IsText - Determines if a string is text: alpha numeric, Carriage
return, line feed, FormFeed character or graphic line
characters (ASCII 10, 12, 13 and 176 to 223). Typical-
ly, this could be used on a string read from a file to
determine the type of file it is.
IsDocs - Determines if a string is document format: All ASCII
characters 0 - 127, and box characters (alphanumeric,
control characters and ASCII 176 to 223). Typically,
this could be used on a string read from a file to
determine if the file is possibly some sort of word
processing format.
Copyright (C) InfoSoft, 1986-1990, 1991 42
Name: IsLeap Type: FUNCTION
Syntax: LeapChk = IsLeap(Year)
Returns a code indicating if the year passed is a leap year (-1)
or not (0). Note that not all years evenly divisible by 4 are leap
years: centennial years (1700, 1800, 1900) are NOT leap years except
those that are divisible by 400 (1600, 2000, 2400). IsLeap is
accurate for years 1200 AD and after.
Name: Julian Type: FUNCTION
Syntax: JDay& = Julian&(month, day, year)
Returns the _TRUE_ julian date for the passed month/day/year.
What many dating schemes call "julian" is merely an ordinal day code
or an ordinal code serialized with the year such as 89102 which is
supposed to indicate the 102nd day of 1988. Even worse, there are
some that return a SERIAL date by calculating the number of days since
1/1/1. These are invariably wrong since they do not take into account
that leap years are NOT every 4 years (years such as 1700, 1900 and
2100 are not leap years); also they tend to ignore that there were 11
days suppressed in 1582 (you went to bed on Oct 4, you woke up on Oct
15).
A modified form of serial dating that is widely used is to
calculate the number of days elapsed since Jan 1, 1900. This modified
julian date method is used by LOTUS 1-2-3 (however they erroneously
recognize 1900 as a leap year probably for simplicity). This is
generally used because invoicing needs and such usually need not
extend back to before 1900 and returns a smaller number (on the order
of 32,000).
A _TRUE_ julian date such as those returned by Julian&, repres-
ent the number of days passed since Jan 1, 4713 BC. Note that Julian&
returns a long integer representing this Julian date. Because
Julian& will not accept dates before Jan 1, 0001 AD, the smallest
number returned is 1721424. That is, Julian does not convert BC dates.
Such a dating method allows for significant, long range date
calculations, such as getting the date for a day x days in the future
or x days ago. Note that in passing the year to Julian, nothing is
assumed. That is, yr = 89 DOES NOT equate to 1989 but 88 AD.
See JulianCvt for examples.
Copyright (C) InfoSoft, 1986-1990, 1991 43
Name: JulianCvt Type: FUNCTION
Syntax: errc = JulianCvt(Ser&, mo, day, yr)
Reconstitutes a long integer formulated by Julian (qv) into a
valid date. The long integer is a _TRUE_ julian date not an ordinal
or serialized date from an arbitrary point. The use of Date, Julian,
JualianCvt and/or DFrmat allow for extensive date calculations. The
function return is non zero for unsupported dates (such as any BC
date). Example:
REM 1. Find the maturity date for a 90 Certificate of '
Deposit purchased 4/5/1989
MatDate& = Julian(4, 5, 1989) ' get julian date for 4/5/1989
CALL JulianCvt(MatDate& + 90, m, d, y) ' convert it + 90
PRINT USING " CD matures in 90 days on ##_/##_/#### ";m;d;y
CALL DFrmat(m, d, y, Mat$)
PRINT "That day is ";Mat$
REM 2. Calculate difference in 2 dates
CALL Date(tm, td, ty) ' get today's date
Today& = Julian(td, tm, ty) ' julian date for today
DueDate& = Julian(dd, dm, dy) ' julian date for a past date
Diff& = ABS(Today& - DueDate&) ' get difference in counts
IF DueDate& > Today& THEN
PRINT "Library book is not due for "; Diff& ; " more days."
ELSE
PRINT "Library Book is "; Diff&; " days overdue!"
PRINT " Pay up $"; (Diff& * LateChg); " or be shot!"
END IF
Copyright (C) InfoSoft, 1986-1990, 1991 44
Name: KBStuff Type: FUNCTION
Syntax: errc = KBStuff(kb$)
This stuffs the keyboard buffer with a string. The default KB
buffer is 16 characters long, but many KB enhancers are available and
used to enlarge this. If this enhancer stores the buffer start-end
addresses in place of the standard low memory location, KBStuff will
recognize it. If the string to stuff is longer than the buffer, the
FUNCTION stuffs as much as the buffer allows and return a code of -2.
If the string to stuff is NULL, the return code is -1. In the case of
-2 returns, you should shorten clear the keyboard and/or parse the
stuff string to smaller sub strings.
Note: Because of the way the BIOS expects to find the buffer start
and end addresses, many enhancers set up a secondary buffer and feed
the low-memory buffer from their own. The size of the buffer in
characters is available from the function KBBuffSize. Also, for some
reason, you may need to add a trailing space if the last character is
a carriage return. Example:
kb$ = "MASM KBStuff" + CHR$(13) + "exit" + CHR$(13) + " "
SHELL ' assemble the program, exit to main program. Note
' trailing space
Name: KBBuffSize Type: FUNCTION
Syntax: size = KBBuffSize
Return the recognized keyboard buffer in low memory. The buffer
can be enlarged, and moved from the DOS default area by a keyboard
enhancer. In most cases, KBBuffSize will not return the size of this
enhanced/enlarged buffer because the KB utility is 'feeding' the low
memory buffer from it's own buffer, in this case, the default 16
character size. Use the return of this function to determine the max
length of string allowed in KBStuff. Example:
MaxChars = KBBuffSize
Name: KeyReady Type: FUNCTION
Syntax: status = KeyReady
Returns zero or non zero to indicate if a key is waiting to be
read from the keyboard input buffer. The advantage to this is that
you can test for the situation WITHOUT actually removing the key from
the buffer - also for users of QB 4.00 and (a), it performs similar to
SLEEP. Example:
IF KeyReady THEN GOSUB MenuFunc
Copyright (C) InfoSoft, 1986-1990, 1991 45
Name: KeyLockCap, KeyLockNum, Type: FUNCTION(s)
KeyLockScrl, KeyLockIns
Syntax: chk = KeyLockCap%
chk = KeyLockNum%
chk = KeyLockScrl%
chk = KeyLockIns%
Checks a specific keyboard lock key (CapsLock, NumLock, Scroll
Lock or Insert) and returns non zero (-1) if it is currently engaged
or zero if it is not. See also KeyShift---.
Name: KeyRateSet/KeyRateClr Type: FUNCTION/SUB
Syntax: errc = KeyRateSet(delay%, rate%)
CALL KeyRateClr
AT systems (as well as PCjr) have the ability to adjust the
keyboard sensitivity rate, (Typematic rate). Sources indicate that
this is an AT capability as opposed to a 80286 feature, so I am unsure
whether this is available to XT/286 systems. KeyRateSet allows you to
tailor the keyboard response so that your program can appear to be
incredibly responsive and ZOOM the cursor to and fro across the
screen. The Delay parameter controls how long after a key is held
down before Typematic begins in the range 0 to 3:
0 - 250 milliseconds 2 - 750 milliseconds
1 - 500 milliseconds 3 - 1000 milliseconds (1 sec)
The Rate parameter controls the Typematic speed or how many characters
per second will be generated. Valid parameters are 0 to 31; parameter
speeds in characters per second (cps):
00 = 30.7 08 = 15.0 16 = 7.5 24 = 3.7
01 = 26.7 09 = 13.3 17 = 6.7 25 = 3.3
02 = 24.0 10 = 12.0 18 = 6.0 26 = 3.0
03 = 21.8 11 = 10.9 19 = 5.5 27 = 2.7
04 = 20.0 12 = 10.0 20 = 5.0 28 = 2.5
05 = 18.8 13 = 9.2 21 = 4.6 29 = 2.3
06 = 17.1 14 = 8.6 22 = 4.3 30 = 2.1
07 = 16.0 15 = 8.0 23 = 4.0 31 = 2.0
To reset BIOS default delay and typematic rate, use KeyRateClr:
CALL KeyRateClr
Note that SMALLER parameters indicate LARGER cps rates and there-
fore FASTER keyboard rates. Also, passing invalid parameters seem to
produce no change in the TypeMatic rate (the BIOS seems to ignore
them). Neither of these routines will execute if a 80286 processor is
not present and KeyRateSet will return an error code of -1 if there is
no 286 present.
Copyright (C) InfoSoft, 1986-1990, 1991 46
Name: KeyShiftAlt, KeyShiftCtrl Type: FUNCTION(s)
KeyShiftRgt, KeyShiftLft
Syntax: chk = KeyShiftAlt%
chk = KeyShiftCtrl%
chk = KeyShiftRgt%
chk = KeyShiftLft%
Checks a specific shift key (Alternate, Control, Left-Shift or
Right-Shift) and returns non zero (-1) if it is currently pressed or
zero if it is not. See also KeyLock---.
Name: LCount Type: FUNCTION
Syntax: NumLines = LCount(fhandle, buffer$)
This may also be called as LineCount.
This is a nifty routine to swiftly scan an existing disk text
file for ASCII 13 (carriage return) and count them (which is a short
cut way of determining lines in a file...). This is handy for
sequential file I/O where you might want to inform the user how long
processing will take or to replace a loop thaty includes a BASIC
function evaluation:
WHILE NOT EOF(x) ' BASIC will execute EOF function
.... ' many times
WEND
FOR x=1 to NumLines ' no basic function!
....
NEXT x loop.
LCOUNT is a function that requires a valid file handle via
FOpen (or the return from FILEATTR) and a scratch buffer - typically,
you will find that a buffer of 4096 characters is sufficient).
An attempt to LCOUNT a standard DOS handle (1-4) is trapped by
LCount and will return an error of -1. LCOUNT is incredibly fast: a
50K test file takes only .5 seconds to count on a 286 system.
LCount leaves the DOS file pointer at the end of the file, so
prior subsequent INPUT and LINE INPUT statements should be preceded by
a BASIC SEEK or a GLib SetFPtr to relocate it to where you want it.
Copyright (C) InfoSoft, 1986-1990, 1991 47
Name: LNameF Type: FUNCTION
Syntax: SwappedName$ = LNameF$(text$)
This data entry routine is handy for rearranging names from some
other source to convert them to "Lastname, FirstName". It works on
names of all types, those with middle initials, just first and middle
initials, multiple middle names. It does not work correctly on Jrs,
people who are the II, III or IV (ad nauseum). In this case, I'd
suggest using BASIC's INSTR and LEFT$ to trim off the Jr or II etc and
append it after the LNAMEF call.
All that is required is that the name have one single trailing
space and another space where the names get swapped. The function
will fail and return a -1 if either condition is found to be not true.
Examples:
"Mary Beth J. Sandra Brooks " => "Brooks, Mary Beth J. Sandra"
"P. T. Barnum Bailey " => "Bailey, P. T. Barnum"
"Thomas Q. McFly III " => "III, Thomas Q. McFly"
"John Public" => "John Public"
This one fails due to no trailing space$
Name: LPrintX Type: Function
Syntax: errc = LPrintX(text$, printer)
Send the string 'text$' to the designated printer (1 - 4). After
each character is printed, it tests to see if it is online and if not,
aborts the operation and returns a non zero error code. This works
fine for Out of Paper and Power Off situations, but those that are
simply offline, it may take quite a while for it to timeout (See
LPTDelay).
Name: LPTDelay Type: SUB
Syntax: CALL LPTDelay(printer, DelayValue)
The system BIOS stores a Time-Out value in low memory that tends
to represent a relative number of seconds required before a time-out
can be detected. The actual value in low memory tends to represent
seconds on 8088/8086 machines and (seconds/4) on 286 systems. This
value is usually 20 meaning anything from a 20 second to 60 or 70
second delay for a timeout. The sub program LPTDelay allows you to
alter this value which can be pretty handy, particularly during
testing and debugging of printer I/O routines and error handlers
(see LPRINTX). The new DelayValue is placed in the time-out table for
the printer specified and would be used in future (parallel) printer
operations. You should either restore this value to 20 or reboot when
done. Remember, that value is not actual seconds to time-out, but
lower numbers will timeout more quickly than higher numbers.
Copyright (C) InfoSoft, 1986-1990, 1991 48
Name: MCsrInc/MCsrDec Type: SUB
Syntax: CALL MCsrInc
CALL MCsrDec
Mouses are curious things. Each call to turn off the mouse
cursor requires an equal number of cursor-on calls to redisplay the
cursor. The mouse driver tracks what is called an internal cursor
flag. Each call to turn off the cursor decrements the counter, each
cursor-on call increments it and if (and only if) the internal flag is
0, the cursor is displayed. Therefore each call to decrement the
flag, needs one increment call if the cursor is to be displayed. And
this does NOT work the other way, if the cursor is on (flag=0) an
additional call to increment the flag has no effect. Finally, we have
no access to be able to read what the cursor flag is to know how many
MCSRINC calls we need to make to display the cursor.
If you are new to mouse programming, take care updating the
screen with the mouse cursor on, it can leave little reverse video
blocks all over, and at times, doing a MSETXY with the cursor on will
produce 2 cursors: one at the old and another at the new location. To
avoid this, turn the mouse cursor off before screen updates, including
(indeed, especially with) screen saves and restores and forced mouse
cursor relocations.
MCSRINC and MCSRDEC increment or decrement the cursor. Knowing
what you do now, it would make sense to track a copy of the internal
flag in your program. If in the course of your program you want to BE
SURE that the cursor is on or off, performing a call to MCSRON or
MCSROFF will do so. However in so doing, the mouse is reset: x and y
range limits, cursor masks, mickey factors, the works. SEE ALSO
MCSRON, MCSROFF
Example: Logical Equivalence
CALL MCsrInc ' InternalFlag=InternalFlag + 1
' IF InternalFlag=0 THEN ShowCursor
CALL MCsrDec ' InternalFlag=InternalFlag - 1
' IF InternalFlag<>0 THEN HideCursor
Name: MCsrOn / MCsrOff Type: SUB
Syntax: CALL MCsrOn
Reset the mouse to power on state and force an unconditional
cursor on or off. This Unconditional Cursor On function also initial-
izes the cursor thus erasing XY ranges, and resetting the mouse cursor
location. See also MCSRINC/MCSRDEC.
Copyright (C) InfoSoft, 1986-1990, 1991 49
Name: MGetXY Type: SUB
Syntax: CALL MGetXY(TextFlag, Mx, My)
As you might expect, this gets the current X,Y location of the
mouse. The location of the text cursor has no bearing on what this
returns. Nor does it matter if the mouse cursor is on or off: MGetXY
returns the CURRENT location of the cursor, NOT the LAST SEEN loca-
tion. Unlike some "other" QB libraries, MGetXY and MSetXY (see also)
use and act upon either 80x25 coordinates or pixel mode thru the use
of a flag. Setting TextFlag to 1 instructs the code to convert the
return to 80x25 coordinates, 0 returns pixel based locations.
Example:
REM get mouse cursor
CALL MGetXY(1, MouseRow, MouseCol)
Name: MLong / MNorm Type: FUNCTION
Syntax: CALL Mlong : CALL MNorm
Control of the sensitivity of the mouse is the ratio by which
one mouse inch moves x number of characters or pixels on the screen
and is called the Mickey Factor.
The default Mickey Factor of the New Microsoft Mouse is about 2
inches per 80 horizontal characters and 1 inch per 25 rows vertically.
MLONG alters the Mickey Factor so that it takes about twice as much
desk space to travel the same screen distance: 4 inches horizontally,
2 inches vertically, while MNORM resets the Mickey back to 2 horizon-
tally, 1 vertically, as does a call to MCSRON (qv).
Name: MRelease/MPress Type: SUB(s)
Syntax: CALL MRelease(lft, rgt)
These mouse routines return the number of mouse button RELEASES
or PRESSES since the last time the mouse driver was polled. One
obvious use of these two routines is to poll the driver to see if a
double click has been executed since the last poll (say, while the
program was off doing a disk access or such). Example:
CALL MRelease(lbutton, rbutton)
CALL MPress(lbutton, rbutton)
Copyright (C) InfoSoft, 1986-1990, 1991 50
Name: MSetXRng / MSetYRng Type: SUB
Syntax: CALL MSetXRng(TextFlag, min, max)
CALL MSetYRng(TextFlag, min, max)
MSetXRng and MSetYRng allow you to limit the minimum and
maximum X and Y range that the mouse cursor is to be allowed to roam
in. A use for this would be to limit the mouse to an area in a window
or a menu. Further, this routine is suitable for use in either text
or graphics modes thru a flag. Example:
REM limit mouse area to a box of 5,1 to 12,40 in 80x25 mode:
TextMode = 1
MinR = 5: MaxR = 12
CALL MSetXRng(TextMode, MinR, MaxR)
MinC = 1: MaxC = 40
CALL msetyrng(TextMode, MinC, MaxC)
Name: MSetXY Type: SUB
Syntax: CALL MSetXY(TFlag, row, col)
This is the simple inverse of MGetXY, setting the current mouse
cursor position. MSetXY works off of either 80 x 25 based coordinates
(if TFlag = 1) or pixel based locations.
Note that the mouse cursor normally seems to default to center
screen (12,40) with a simple cursor on call (MCSRINC, MCSRON).
Example: ' set Mcursor position to row 20, column 60
CALL MSetXY(1, 20, 60)
Name: MSMouse Type: SUB
Syntax: CALL MSMouse(ax, bx, cx, dx)
While the mouse functions incorporated into GLIB are fairly
comprehensive, there may be times when you want to execute one of the
more esoteric ones like cursor customization. MSMouse provides for a
way of executing any general mouse function directly to the Microsoft
Mouse Driver. AX, BX, CX and DX are the registers (also referred to
as M1, M2, M3 and M4 in some mouse references). AX (or M1) is used to
indicate the function to execute and the others may need to be loaded
with other required parameters. After executing the interrupt, the
parameters are replaced with the register contents after that inter-
rupt. If you do not have a decent mouse reference there are a few on
the Information Booth - or call and leave a note and we will look it
up for you.
Copyright (C) InfoSoft, 1986-1990, 1991 51
Name: MSetCsr Type: SUB
Syntax: CALL MSetCsr
This is a rather specialized routine for the mouse. Some of
the less compatible mice require a little tweaking to get the cursor
to display. If you have trouble getting a cursor to display, calling
MSetCSR should set the mask so that it does display when the cursor is
on. It appears to have no ill effect on mice who do not need it.
Name: MStatus Type: SUB
Syntax: CALL MStatus(lft, rgt)
This returns a 0/1 indicating if the left or right mouse button
is currently being pressed.
Name: MType Type: FUNCTION
MouseType = MType
This routine returns whether a mouse exists or not as the
number of mouse buttons. Naturally, that means 0, 2 and 3 are the
only MTYPE returns you should expect.
Example:
MouseExist = MType
IF MouseExist THEN
..
..
END IF
Copyright (C) InfoSoft, 1986-1990, 1991 52
Name: MemCompA Type: FUNCTION
Syntax: code = MemCompA(SEG Arry1, SEG Arry2, words)
Compares the listed number of WORDS of two memory sections (ty-
pically this would be elements of 2 arrays) and returns the BYTE
offset where they mismatch or 0 if the 2 things to compare are ident-
ical. This can be helpful in UnDo type functions or to determine if
I/O in a SUB altered an array. See also MemCompV. Eg:
REDIM AArray(10), BArray(10)
code = MemCompA(AArray(1), BArray(1), 20) ' 10 * 2 = 20 bytes
IF Code THEN
PRINT "Arrays are not identical"
END IF
Name: MemCompV Type: FUNCTION
Syntax: offs = MemCompV(SEG Arry)
Compares the video display to the next 4000 bytes in the array
passed and returns an offset of where they differ or 0 if they are
identical. Snow is checked for if a CGA is detected. Note that the
return will indicate a screen OFFSET from (1,1) where the screen
differs from the array. Note also that the array offset passed can be
any position. The returned value is a WORD offset that allows us to
easily convert to Row/Column coordinates. See also MemCompA.
Example:
scrn = 4001 ' point to screen offset 3
CALL SaveScrn(Array(scrn)) ' save video to position 3
GOSUB DoStuff
offset = MemCmpV(Array(scrn))
IF offset THEN
PRINT "Screen altered at offset: ";offset
END IF
Name: MemMove Type: SUB
Syntax: CALL MemMove(SEG src, SEG dest, words)
MemMove works like the standard 'C' function of the same name - it
moves a block of memory from the source to the destination. One
excellent use for this is to replicate arrays. Make sure that the
destination array is large enough for the number of bytes to copy so
as not to write to an unallocated block of memory. Example:
DECLARE SUB MemMove(SEG Src%, SEG Dest%)
..
..
REDIM Arry1(2000), Arry2(2000)
..
CALL MemMove (Arry1(1), Arry(2), 2000) ' 2000 = 2000 elements
Copyright (C) InfoSoft, 1986-1990, 1991 53
Name: MenuCtrl Type: FUNCTION
Syntax: code = MenuCtrl
MENUCTRL is a keyboard / menu control module that is totally
network compatible to trap specific keys. As such, it is ideal for
menu driven routines. When called, the routine intercepts all key-
board activity exiting only if a number key or function key is pressed
- any other input is ignored. MENUCTRL returns the value of the key
or function key pressed, ie '1' and/or '[F1]' return 1, '2' and/or
'[F2]' returns 2 etc. Pressing [Esc] returns 15.
Name: MergeArray Type: SUB
Syntax: CALL MergeArray(SEG Mask, SEG Dest, Words)
Given two arrays (presumably screen images), all characters in
MASK array are transferred to the destination array EXCEPT when they
are a space. One use for this would be to superimpose a grid or other
mask over an image then ScrnRest it to the video for reference points.
If you retain an unaltered image of it, you could allow the user to
flip back and forth. Pseudo Animation is another possibility. Note
that the number of WORDS or INTEGERS is used rather than BYTES. See
also MergeScrn. Example:
DECLARE SUB MergeArray(SEG Mask, SEG Dest, ByteCnt)
REDIM Scrns(2000), Grid(2000) ' allocate memory
GOSUB FillGrid ' put lines in Grid()
GOSUB GetScrn ' put whatever in array
CALL MergeArray(Grid(1), Scrns(2001), 2000)
' Merge Grid over Screen
CALL RestScrn(Scrns(1)) ' display end result
Name: MergeScrn Type: SUB
Syntax: CALL MergeScrn(SEG Mask)
This is similar to MergeArray except the mask is merged directly
to the screen and 4000 bytes is assumed. Example:
DECLARE SUB MergeScrn(SEG Mask%)
REDIM Grid(2000) ' allocate memory
GOSUB FillGrid ' put lines in Grid()
CALL MergeScrn(Grid(1)) ' place GRID over CRT display
Copyright (C) InfoSoft, 1986-1990, 1991 54
Name: MFED Type: FUNCTION (BASIC)
Syntax: FCode = MFed(ed$, fsiz, Macro$())
(Complete documentation and use is in MACROxx.DOC)
This is a very comprehensive text input routine that allows you
extensive control over user input. It is used to exert total control
over the user's input, recognizing all cursor and function keys.
Ed$ - string to edit
fsiz - maximum length allowed
Macro$() - array of strings to be invoked with [Alt- ] key
strokes.
Be sure to carefully read MACROxx.DOC for set up of the COMMON block!
Name: MHZ Type: FUNCTION
Syntax: speed = MHZ
This returns the approximate, effective MegaHertz the system is
run at. Sound vague enough? This return is the result of a very
quick benchmark. It is "approximate" and "effective" Mhz because it
will be off a little depending on the number of wait states of the
machine, and some faster PC clones return falsely high numbers.
MHZ returns the speed factor as a whole number: that is a
return of 935 means an effective MHZ speed of 9.35. Divide the return
by 100. It is advised that you cross reference the speed with the
chip: if MHZ returns 1400 but CPUINFO indicates a 8088 machine, you
know the speed is wrong and that the PC is more likely 8 to 10 MHz.
Name: MilliDelay Type: SUB
Syntax: CALL MilliDelay(millisecs)
MilliDelay works like DELAY in that it enables you to insert
controllable delays or slow downs into your code for effect or to
allow the end user time to digest the screen. This halts processing a
given number of milliseconds (100 milliseconds minimum) and works out
great when a full second is too long. Example: CALL mdly(100)
' delay .1 seconds
Copyright (C) InfoSoft, 1986-1990, 1991 55
Name: NFrmat Type: FUNCTION (BASIC)
Syntax: errc = NFrmat(numst$, mode, point)
This routine allows for extensive numeric string processing. You
can format a numeric string to pre determined formats such as 7 or 10
digit phone numbers, social security or an account number type format.
Parameters:
numst$ = string to process (presumably numeric)
p = position of a single "-" for mode 4 (account number
numbers...)
m = mode or level of processing to perform:
Mode 1 = Seven digit phone number ie: ###-####
2 = Formatting to 10 phone type ie: (xxx) xxx-xxxx
3 = Formatting to social security style ie: xxx-xx-xxxx
4 = Format with "-" in position p.
To get (316)-684-8744 out of 3166848744:
errc = NFrmat(st$, 2, 0)
Mode 4 Example:
INPUT "Account Number:", st$ ' they key in 3145678
errc = NFrmat(st$, 4, 3)
PRINT st$ ' output would be 31-45678
Errc returns -1 on an unknown mode or format code.
Name: NLON / NLOFF Type: FUNCTION
Syntax: CALL NLOn : CALL NLOff
Sets the Keyboard Num Lock key to on (NLON) or off (NLOFF).
Name: NoBoot Type: SUB
Syntax: CALL NoBoot(func)
This "steals" the keyboard interrupt to watch for the simultaneous
press of Ctrl-Alt-Del, which it promptly disregards. Since this does
act to replace the keyboard handler, it is imperative that you un-
install it before your program terminates, as well as part of any
error handler you have and certainly before hitting Ctrl-Break to drop
to QB editor level when running in the QB environment. Function 0 un-
installs NoBoot, any non zero value installs it - take care not to
install multiple copies! Example:
CALL NoBoot(1) ' install it
CALL NoBoot(0) ' uninstall it
Copyright (C) InfoSoft, 1986-1990, 1991 56
Name: Painter Type: SUB
Syntax: CALL Painter(Trow, Lcol, Brow, Rcol, newattr)
This re-colors the specified area of the screen with the new color
specified in newattr. This is ideal and well suited for bar menu
type functions to recolor or hi-light the current selection, or for
modifying a color screen for mono use (Turn off the video, repaint it
and turn it back on - then SAVE it for future use!) Example: Recolor
right half of screen to yellow on red:
CALL Painter(1, 40, 25, 80, 78)
Name: ParseFileSpec Type: FUNCTION
Syntax: errc = ParseFileSpec(raw$, drv$, path$, fil$, ext$)
Given a legal filename, this will parse it into it's component
parts and devoid of trivial punctuation (colons and dots are removed,
backslashes are not). Being in assembler, you must initialize the
return parameters to avoid string space corrupt errors:
Drv$ - minimum 1 for drive character storage
Path$ - Up to 64 characters
fil$ - up to 12 characters
ext$ - 3 characters
If the actual size in raw$ exceeds the amount you pass, as much as
will fit will be returned, and an error code will be returned to
indicate you passed a short string: ext$ = -1, fil$ = -2, path$ = -3,
drv$ = -4. Additionally, if raw$ is NULL, -5 is returned.
Name: PCase Type: FUNCTION
Syntax: p$ = PCase$(p$)
PCase can also be invoked with the longer name ProperCase.
Converts a passed test string to 'proper case'. That is, "bob
smith" is returned as "Bob Smith". Prior to calling PCASE convert the
string to lower case:
x$ = "TIMOTHY FOOBAR"
x$ = LCASE$(x$)
CALL PCase(x$)
Name: PGetCh$ Type: FUNCTION
Syntax: ret$ = PGetCH$(prompt$, row, attr, okay$)
This routine is similar to GETCH in that it allows keyboard
input only from a predefined string, is ANSI compatible and network
functional, but additionally allows the addition of an automatically
centered prompt. By predefining a number of prompts and input masks,
a variety of easy to use prompt-and-allowable-input-masks can be setup
for very easy use. See also GETCH, DialogBox. Example: Display a
prompt on line 24, in yellow on red, allowing only "YNA" input:
prompt$ = "Are You Sure Y/N/Abort"
okay$ = "YNA": ky$ = " "
CALL pgetch(prompt$, 24, 78, okay$, ky$)
Copyright (C) InfoSoft, 1986-1990, 1991 57
Name: PhDrvSet Type: SUB
PhDrvClr Type: SUB
PhDrvStat Type: FUNCTION
Syntax: CALL PhDrvSet
CALL PhDrvClr
flag = PhDrvStat
Since DOS uses Drive A: as both A: and B: on single floppy sys-
tems, it uses a flag to keep track of what state it is in. PhDrvClr
and PhDrvSet allow you to manipulate this flag to avoid the "Insert
disk in drive B:..." message in operations where you wish to use a
single floppy as both A: and B:. PhDrvSet sets the flag to indicate
that drive A: is acting as B:, PhDrvClr clears it to A: acting as A:.
PhDrvStat returns the current status of the flag 0 (clear) or 1
(set). Note that should supply your own message and keypress routine
to allow the end user time to swap disks, but certainly, you can do a
better job than DOS. Also, you should reset the flag when done.
Example:
..
CopyToB:
CALL PhDrvSet ' Set A: to B:
IF DrvError("B") THEN
GOSUB DrvNotReady ' test it
END IF
GOSUB CopyBlock ' perform operation
CALL PhDrvClr ' clear flag (A: = A:)
RETURN
Name: PrgName Type: FUNCTION
Syntax: errc = PrgName$
When we wrote BCLock (a program that makes your compiled program
aware of changes to itself either from tampering or virus infections),
we needed a way to get our OWN file/path name. This function is
functionally identical to C's 'argv[0]', returning the full drive and
path name of the program executing. This can be very useful for those
that wish to store operating parameters in the EXE file itself rather
than in a CFG or INI file. (The questionable theory of this is to
open the EXE file and store a TYPE structure of parameters at the end
of the EXE. This is all fine until the user attempts to run the
program outside the current directory (via path) or they rename your
.EXE file - then this nifty idea comes crashing to an insolvable
halt).
The return from PrgName will contain the drive/pathname of the
currently executing program. This return string can then be parsed
into components if desired. (See also ArgCnt, ArgVar and GetCmdStr$
et al). Note: PrgName will return different information in the QB
environment than as a .EXE file, because the program running is QB.EXE
and NOT your program - yet. Example:
MyName$ = PrgName$ ' returns "C:\DIRNAME\FOOBAR.EXE"
PRINT "Program running is: "; MyName$
Copyright (C) InfoSoft, 1986-1990, 1991 58
Name: PrtQueStat Type: FUNCTION
Syntax: RetCode = PrtQueStat
Fetches the status of the DOS print queue. Note that this is the
PRINT.COM file that comes with DOS and the function is informing you
if PRINT is resident and therefore other PrtQue functions are avail-
able to you. Possible returns are:
-1 = PRINT.COM is installed and resident
1 = PRINT.COM not installed and it is NOT ok to install
0 = PRINT.COM not installed, ok to install
NB: AT LEAST QB 4.0 (maybe 4.00(a) and possibly 4.00(b)) has a
problem getting along with PRINT.COM. Our testing with PRINT.COM from
DOS 3.1 and QB 4.00(b), BASCOM 6.0 and QB 4.5 has resulted in no
problems but this is no guaranty of your results.
Name: PrtQueSubmit Type: FUNCTION
Syntax: errc = PrtQueSubmit(fil$)
Submits a file to the DOS print spooler. The file must exist, and
occasionally it has seemed that we needed to pass a fully qualified
drive/path name before PRINT.COM would accept it (see ExpandPath),
however the name may not include wildcards (? or *). Any return other
than 0 indicates an error:
0 = File accepted into PrtQue
1 = Error accepting file
Name: PrtQueDelete Type: FUNCTION
Syntax: errc = PrtQueDelete(fil$)
Deletes the specified filename from the Printqueue, the file must
have been previously submitted via PrtquSubmit, and while it responds
to wildcards, a fully qualified drive/pathname may be required (see
ExpandPath). Note that if the file you wish to delete or remove from
the Print Queue is currently being printed, that printing may not halt
immediately due to any buffering done by the printer. Any return
other than 0 indicates an error.
Name: PrtQueCancel Type: FUNCTION
Syntax: errc = PrtQueCanel
Cancels ALL files currently in the print queue (these would have
been submitted via PrtQueSubmit). Note that in cancelling all files
queued, that PRINT.COM prints a message on the printer noting the
cancellation. This is DOS or PRINT.COM's doing, not mine. Any return
other than zero indicates an error.
Copyright (C) InfoSoft, 1986-1990, 1991 59
Name: PrtScrn Type: SUB
Syntax: CALL PrtScrn
This very simply sends the current display to the printer.
Name: PrtScEnable Type: SUB
PrtScDisable Type: SUB
Syntax: CALL PrtScDisable
These 2 routines act to toggle the ability of the system to
perform a Print Screen function. This can be handy in cases where the
information on screen is sensitive to the extent that your application
needs to prevent it from being printed. Note that TSR type dump-to-
disk utilities will still work, but once installed Shift-PrtSc will
not work until the system is re-booted or PrtScEnable is called.
Name: PtrInit Type: SUB
Syntax: CALL PtrInit(prtnum)
Initialize the printer, and if the offline button is set to
OFFLINE, it will put it online (most Epsons anyway) and set the
printer to TOF (Top Of Form). Call it with the designated printer
port to initialize (1 to 3). See also PtrStat. Example:
CALL PtrInit(PrinterNum)
Name: PtrStat Type: FUNCTION
Syntax: status = PtrStat(PtrNum)
Where PtrInit intializes the printer, PtrStat returns the status
of a designated printer in the form of 0, -1 so you can evaluate the
printer status prior to a print function.
Pass PtrStat the printer number to test (1-3) as a variable and
the variable will be returned as 0 or -1 indicating the status.
NOTE: When testing the status immediately after calling PtrInit,
allow 1 or 2 seconds before calling PSTAT, this is to avoid polling
the printer while it is still initializing. PtrStat will always
indicate the printer online if a spooler is installed. Example:
prtnum=1 ' printer to access
CALL PtrInit(prtnum)
CALL dly(2) ' wait for the low tech item to finish
stat = PtrStat(prtnum)
IF stat THEN
...perform print job ...
END IF
Copyright (C) InfoSoft, 1986-1990, 1991 60
Name: QCalc& Type: FUNCTION
Syntax: Result& = QCalc&(TRow, LCol, BodyAttr, ScrnAttr,_
SpeedFactor)
(QCalc is fully documented in MACRO17.DOC). TRow and LCol is the
Top, Left corner of the calculator, Body and Scrn are the attributes
for the calculator body and screen and SpeedFactor controls the type
ahead, display and beep speed.
Name: QBLoaded Type: FUNCTION
Syntax: Result = QBLoaded
QBLoaded may also be declared and invoked as QBL.
This simply checks to see if the currently executing program is
QB.EXE. The use for this is esoteric (although users of an old QB LIB
collection that works differently in EXE form as in the QB Editor
should LOVE this one!) but allows you to determine of the process
executing in memory is an .EXE or a program image being executed by
QB.EXE. Possible returns are:
0 QB Not loaded - EXE file executing
1 QB.EXE loaded
Name: QPrint Type: SUB
Syntax: CALL QPrint(text$, row, col, attr)
This is a replacement for BASIC's native PRINT statement. While
QB4 and later are much quicker than earlier versions, QPrint is still
a bit quicker and allows for other features. Parameters:
text$ - String to print
row - Row of screen to print text to.
col - Column of screen to print to
attr - color attributes to use for the text. This is calculated in
the same manner as the attribute is for Windows, ErrMsg etc
Example:
msg$="QPRINT is very, very FAST !!"
CALL QuikPrt(msg$, 2, 2, MakeAttr(14,4))
or directly,
CALL QPRINT("QUIKPRT is very, very FAST !!", 2, 2, 78)
Note the nested Function: MakeAttr nested within the CALL to
QPRINT: BASIC will execute MakeAttr first and pass the RETURN to
QPRINT - however if you are going to use and reuse the attribute, you
should assign it to a variable.
Name: RamFree Type: FUNCTION
Syntax: ram = RamFree
Returns the amount of memory installed in the machine.
Copyright (C) InfoSoft, 1986-1990, 1991 61
Name: ReadScrn Type: SUB
Syntax: CALL ReadScrn(text$)
This is like BASIC's SCREEN function except that it is a much
faster (on an order of magnitude) way to read text from the screen.
ReadScrn uses the current cursor location as the starting point and
reads as many characters as you have spaces in the passed string.
This is critical, since ASM routines cannot alter string lengths, if
you want 13 characters, text$ must be initialized to SPACE$(13).
Example:
ScrnText$=SPACE$(15)
LOCATE 12, 15
CALL ReadScrn(scrntext$)
Name: RepAttr Type: SUB
Syntax: CALL RepAttr(OldAttr, NewAttr)
Selectively replaces attributes on the video display. All occur-
rences of OldAttr are replaced by NewAttr.
Name: ReverseString Type: SUB
Syntax: CALL ReverseString(s$)
May also be invoked with the shorter name RevStr
Reverses all characters in a string very quickly. When used in
conjunction with XLATE, that can be a fairly good encryption system.
Example:
x$ = "PassWord"
CALL RevStr(x$) ' returns as "droWssaP"
Name: RINSTR Type: FUNCTION
Syntax: position = RINSTR(test$, ch$)
Returns the LAST occurrence of a character in a string. This
works conversely to BASIC's INSTR, which returns the first occurrence,
and is faster and much more code efficient than a loop to keep testing
INSTR until the end of the string is reached. The character location
however is still returned from the left. Note: RINSTR works only
on character seeks, not on sub strings like INSTR does. That is, in
the case of [j = RINSTR("ABCDEFG","A@B") ], RINSTR will only seek and
match on "A", not "A@B". Multiple passes thru RINSTR, however seeking
each successive character in a sub string could be accomplished.
Example:
DECLARE FUNCTION RINSTR%(searched$, seek$)
..
test$="123456x890" : char$="x"
l = RINSTR(test$, char$) ' returns 7
Copyright (C) InfoSoft, 1986-1990, 1991 62
Name: RTCDateSet/RTCDateGet Type: FUNCTION(s)
Syntax: errc = RTCDateGet(mo, day, yr)
errc = RTCDateSet(mo, day, yr)
When running on an AT/286 system, this allows you to fetch or set
the date held by the onboard Real Time Clock. While PC's can have
battery maintained times, they tend to vary greatly from system to
system as to how to access the data held within. For this reason,
this will return an error code if the system is not a 286:
-2 = System not an AT/286
-1 = Time/Date update in progress (try again)
See also RTCTimeGet/RTCTimeSet
Name: RTCTimeSet/RTCTimeGet Type: FUNCTION(s)
Syntax: errc = RTCTimeGet(hr, min, sec, hund)
errc = RTCTimeSet(hr, min, sec, hund)
AT/286 systems include an onboard battery maintained clock that
maintains the time and date when the system is off. This routine will
read or set the time portion held there. This can be handy to make
sure that no one is trying to trick your application by resetting the
DOS time (or date), by reading the time (or date) directly from CMOS.
For additional info see RTCDateGet/RTCDateSet.
Name: RunCmdL Type: SUB
Syntax: CALL RunCmdL(cmd$)
May also be called with RunCommandLine
If you have ever used QB's RUN to execute another program, you
know that it is impossible to change or alter the command line - until
now. As is, QB passes the original PSP (Program Segment Prefix) which
contains the environment and the command tail to these subsequent
processes. RunCmdL basically alters COMMAND$ so that you can pass a
new command tail to a RUN program. Simply pass RunCmdL whatever new
COMMAND$ you want the RUN program to act on, and that RUN program will
have a new COMMAND$. The maximum length is 128 characters. DOS may
overwrite the first few characters of cmd$ with the filename to RUN,
so be sure to pre pad it with enough spaces to compensate. To cancel
a Command Tail, simply pass a single space more than that filename
length. Example:
cmd$ = " /C /1 foobar.dat COLOR" ' note leading spaces
CALL RunCmdL(c$)
RUN "Foobar"
Note the leading spaces enough to allow FOOBAR to be overlayed
plus one space as a separator. RunCmdL works in the QB environment as
well as a EXE.
Copyright (C) InfoSoft, 1986-1990, 1991 63
Name: SaveScrn/RestScrn Type: SUB
Syntax: CALL SaveScrn(SEG arry(x))
CALL RestScrn(SEG arry(x))
The SaveScrn routine saves the current screen display to an
integer array then via RestScrn you can restore that saved screen to
the display. This is very handy in a routine in situations where you
might want to pop a help window to the display. You could save the
current screen, display a help window or screen, then upon command
redisplay the original screen. The GLIB implementation is very
undemanding - the array which we save to and from can be DYNAMIC or
STATIC, the Save and Restore screen functions will work with either
type of array, and both in EXE files and from the QB environment.
Additionally, Save/Rest Scrn not only recognizes extended video
type (like VGA, EGA and MCGA), but video modes other than 80*25 are
supported - if your VGA is in 80 * 43 mode, Save/Rest Scrn will see
that and save 3440 character/attribute pairs rather than 2000 (be sure
to allow for 3440 integers rather than 2000 in this case!). Example:
DECLARE SUB SaveScrn(SEG Array%)
DECLARE SUB RestScrn(SEG Array)
..
..
REDIM ScrnArry(10000) ' enough for 5 (80 x 25) screens
CALL SaveScrn(ScrArry(1)) ' save current screen to pos 1
CALL RestScrn(ScrArry(4000)) ' restore from screen pos 3
INTEGER variables can be used to point to the screen offsets:
Scrn1 = 1 : Scrn2 = 2001 ' simple variable
CONST SCRN3 = 4001, SCRN4 = 6001 ' constants work too!
CALL SaveScrn(ScrArry(Scrn1)) ' save display to offset 1
GOSUB DoHELP
CALL RestScrn(ScrArry(SCRN4)) ' restore from offset 6001
For more information, examine the demo source code, as these 2
routines are used quite a bit. In the demo, a deliberate delay is
used in some cases to slow down the save and restore process to allow
you time to perceive some processes.
Copyright (C) InfoSoft, 1986-1990, 1991 64
Name: SaveWindow Type: SUB
RestWindow
Syntax: CALL SaveWindow(SEG arry(x), TR, LC, BR, LC)
CALL RestWindow(SEG arry(x), TR, LC, BR, LC)
These may be invoked with the shorter names SvWdw and RstWdw
Where SaveScrn and RestScrn save and restore the entire screen
(taking 4000 bytes of memory to do so), Save / RestWindow save and
restore only a portion of the screen as might be needed to manage the
section of the screen that will be altered from a window display.
Since the size of the array required varies depending on the size of
the window, use BuffCalc to calculate the precise size needed.
Example:
DECLARE SUB SaveWindow(SEG arry, TR, LC, BR, RC)
DECLARE SUB RestWindow(SEG arry, TR, LC, BR, RC)
..
..
..
CASE 17 ' Help function
size = BuffCalc(1, 40, 20, 80)
REDIM HelpWdw(size) ' get array size
CALL SaveWindow(HelpWdw(1), 1, 40, 20, 80)
' save screen under wdw
CALL HELP ' do help
CALL RestWindow(HelpWdw(1), 1, 40, 20, 80)
..
..
See SvScrn / RstScrn for general info on screen save techniques.
Name: ScrlOn / ScrlOff Type: SUB
Syntax: CALL ScrlOn
Toggles the scroll lock key on or off. If the keyboard is eq-
uipped with LED's, they are also toggled to the appropriate state.
Copyright (C) InfoSoft, 1986-1990, 1991 65
Name: ScrnDump Type: FUNCTION
Syntax: errc = ScrnDump(fhandle)
Very simply, this reads thru video memory, removes the attribute
byte and dumps the text to disk, adding a CR/LF pair every 80th
character except on the last line. This is very fast and works with a
DOS file handle - either open the file with FOPEN or use BASIC's
FILEATTR to ascertain the handle from a BASIC fileno. If you use
BASIC's "OPEN ... FOR", ScrnDump will respect the mode (OUTPUT or
APPEND) and it would be VERY unlikely that any error occurs because
the legitimacy of the file name would have been check by BASIC when
OPENed.
ScrnDump will return errc as 6 if the handle is not valid - the only
likely error short of a disk error. Example:
ff = FREEFILE ' get handle
OPEN "scrndump.fil" FOR APPEND AS #ff ' open file
fh = FILEATTR(ff,2) ' fileno => fhandle
errc = ScrnDump(fh)
Name: ScrnDumpB Type: FUNCTION
Syntax: errc = ScrnDumpB(fhandle)
This works very similar to ScrnDump, except that rather than
dumping a text file, it leaves video memory in binary format. This is
similar to the BSAVE function in BASIC except that the signature bytes
are omitted and you can APPEND the screen image to an existing file.
In so doing, you can basically make a binary screen library. Add-
itionally some periodic bugs in BSAVE with DOS 2.0 and/or QB are
avoided.
Example:
ff = FREEFILE ' get handle
OPEN "scrndump.fil" FOR APPEND AS #ff ' open file
fh = FILEATTR(ff,2) ' fileno => fhandle
errc = ScrnDumpB(fh)
Name: ScrnWash Type: SUB
Syntax: CALL ScrnWash
ScrnWash may also be called as MonoScrn
ScrnWash removes the color from the screen display in order to
make it suitable for a Monochrome or Composite system. ScrnWash
converts colors 1 to 6 to 7 (white) and converts colors 9 to 14 to 15
(hi int white). In effect, it washes the colors out to black, white
and hi intensity white.
Copyright (C) InfoSoft, 1986-1990, 1991 66
Name: ScrollL/ScrollR Type: SUB
Syntax: CALL ScrollL(Tr, Lc, Br, Rc, FillAttr, NumLines)
Syntax: CALL ScrollR(Tr, Lc, Br, Rc, FillAttr, NumLines)
These may also be called as ScrlLeft and ScrlRght
This routine scrolls the entire screen or a portion of it left
or right the designated number of lines. The scrolled or blanked
portion of the screen is filled in with the designated attribute if
the attribute value is 0 to 128. If the attribute value is -1, then
the attribute is left unchanged. Example:
CALL ScrlLeft(1, 1, 25, 80, -1, 4) ' scroll screen left 4 cols
CALL ScrlRight(5, 5, 18, 60, 7, 15) ' scroll a window right 15 cols
Name: ScrollUp / ScrollDn Type: SUB
Syntax: CALL ScrollUp(TRow, LCol, BRow, RCol, attr, Num)
CALL ScrollDn(TRow, LCol, BRow, RCol, attr, Num)
These 2 routines scroll a portion (or all) of the current display
up or down a user defined number of times. SCROLL allows for you to
set the parameters for all four boundaries: top, bottom, left and
right. Additionally, you designate the number of lines to scroll.
Designating 0 as the number of lines to scroll, clears the screen.
Parameters:
Top, left, bottom and right, relate to the bounds of the area to
scroll, attribute is the color to use to fill the portion of the
screen affected, and Num is the number of lines to scroll. Example:
num=12 : top=1 : lft=1 : bttm=12 : rght=79
CALL ScrollDn(top, lft, bttm, rght, 112, num)
' scrolls lines 1 to 12 down 12 lines - lines 13 to 25
' are lost
CALL ScrollUp(13, 1, 25, 79, 7, 12)
' scrolls lines 12 to 25 up 12 lines - with 13-25
' becoming blank.
CALL ScrollD(1, 1, 25, 79, 7, 25)
' Clears the screen with the display scrolling down off
' the screen
Name: SetDrv Type: SUB
Syntax: CALL SetDrv(drv$)
Sets or resets the default drive. To set the drive, simply pass
it the letter, upper or lower case, to log into. This removes the
ambiguity of drive numbers (Hmm, is drive 1 A: or B: in this case...).
SetDrv returns nothing and if passed a bad parameter, DOS simply
rejects it leaving the default drive unchanged. Example:
drv$="d"
CALL setdrv(drv$)
Copyright (C) InfoSoft, 1986-1990, 1991 67
Name: SetErrLvl Type: SUB
Syntax: CALL SetErrLvl(ERRORLEVEL)
Sets return code upon program termination. These can be read
from DOS via as "ERRORLEVELs" in batch files. This routine should be
called near the end of a program. It WILL NOT terminate your program,
upon execution, but will merely change the QB RTL (Run Time Library)
default return code ("ERRORLEVEL") so that when the program is ter-
minated with END or SYSTEM, your redefined error level is used.
Since this is an interrupt service routine, ie we take over the
DOS interrupt function to terminate, it MUST NOT be called more than
once in a program. Further, since there is no way to uninstall it, it
should not be called from inside the environment - you should not
revector interrupts without installing them before dropping to QB
editor level. (This goes for NoBoot, Clock and DrvErr too, but they
can be uninstalled!).
Example 1:
CALL SetErrLvl(code) ' terminate and set "ERRORLEVEL"
Example 2:
IF ErrCode THEN
PRINT "ABEND"
CALL SetErrLvl(ErrCode)
ELSE
PRINT "Normal Termination"
SYSTEM
END IF
Name: ShareInst Type: FUNCTION
Syntax: RetCode = ShareInst
Returns a non zero value if SHARE is installed. This can be
helpful at the start of a program in determining the type of file
access to use.
Example:
IF ShareInst = 0 THEN
PRINT "Sorry, this version requires SHARE.EXE be installed!"
END IF
Name: ShiftLeftI/ShiftRightI Type: FUNCTION
Syntax: Result = ShiftLeftI(value, ShiftCount)
Result = ShiftRightI(value, ShiftCount)
These can also be called by the similar assembler instruction
names ShlI and ShrI.
This returns RESULT after the integer VALUE has been shifted left
or right the number of times indicated in ShiftCount. Besides provid-
ing a quick multiplication and division method, it is handy for bit
operations such as isolating the date bits in a DATE word for in-
stance.
Copyright (C) InfoSoft, 1986-1990, 1991 68
Name: ShutDown Type: SUB
Syntax: CALL ShutDown(graphics)
This parks any fixed disks in the system, shuts down the system
and via if the graphics switch is set (non zero), a graphic display of
the Big Red Switch is drawn center screen. HALT provides a more
economical version of ShutDown by skipping the parking and picture.
Name: Sleeper Type: SUB
Syntax: CALL Sleeper(x)
This works identically to BASIC's intrinsic SLEEP by waiting x
secs for a keypress or, if x is set to zero it will wait forever for
that keypress. Using SLEEP implicitly sets up an EVENT trap. That
is, if you link your program with the NOEVENT.OBJ stub file, some
versions of the compiler will cause your program will lock up or bomb
out when it reaches the SLEEP statement because it needs the EVENT
code that you stubbed out. Sleeper allows you to still link with NO-
EVENT.OBJ and/or produce smaller code size by omitting all the event
trapping code.
Name: SpkrOn/SpkrOff Type: SUB
Syntax: Call SpkrOn
Call SpkrOff
SpkrOn may also be called as SpeakerOn and SpkrOff as SpeakerOff
These enable or disable the PC speaker. With the speaker toggled
off, BASIC's SOUND statements will execute, but no sound will be
emitted. Allowing for total program configuration, if the end user
does not want sound, you can kill the speaker with one line of code:
CALL SpkrOff
rather then the following in hundreds of places in your code:
IF SoundFXON THEN
FOR x = 1 TO 8
SOUND f, d
NEXT x
END IF
Note that good programming practices would dictate that you
restore the speaker state (SpkrOn) before your program terminates.
Name: SpkrSnd Type: SUB
Syntax: Call SpkrSnd(BYVAL freq, BYVAL dur)
SpkrSnd may also be called as SpeakerSnd
Emits a tome on the PC speaker of the specified frequency for the
number of clock ticks specified by duration. The advantage to this
over SOUND is that this adds less overhead and is slightly faster.
Example: CALL SpkrSnd(750, 5) ' Equivalent to BEEP
Copyright (C) InfoSoft, 1986-1990, 1991 69
Name: Soundex/SoundexM Type: FUNCTION
Syntax: code$ = Soundex(text$)
The Soundex process is a fabulous algorithm developed by Michael
Baldwin of AT&T Labs. Soundex allows you to convert English text,
words or names to a fundamental code so that 'botl', 'bottel', 'btl'
and 'bottle' (and several more misspellings and botched abbreviations)
would all look alike to your code. In searching a large databases for
a name, when using Soundex, the end user really only needs to know
'sort of' how it SOUNDS (not spelled)!
To clarify what Soundex does, note that both CATSUP and KETCHUP
return a similar Soundex code. This Soundex code is expressed as a 4
character code in the form '?nnn' where '?' is the first letter of the
word/name, and each 'n' is the balance of the encoded word or name.
If the encoding does not take up all 3 characters the balance is
filled with zeroes (eg: L300).
One drawback is that names or words with foreign origins may not
come back with logical Soundex codes: 'lummox' (a lazy oaf) returns
the same code as 'Lemieux'. Now, Mr. Lemieux may indeed be an oaf,
but the words do not sound at all alike.
SoundexM is a modification to the Soundex routine that follows the
conventional algorithm, but rather than being in "?nnn" format, it
encodes the first character too. The advantage of this is that the
code can then be made part of a file record and it takes up only 2
bytes (INTEGER). Additionally, when searching large databases, with
the first letter coded or quantified, record search and retrieval
using binary searches and other fast hashing techniques can be used
with great effect.
Examples:
Word Soundex SoundexM
----- ------- --------
Catsup C321 2321
Ketchup K321 2321
Lemieux L520 4520
Ohlemeyer O456 0456
AirReturnFan A636 0636
LLoyd L300 4300 **
Ladd L300 4300 **
( ** many Soundex algorithms fail on these)
I tend to use a combination of both Soundex and SoundexM: I store
the Soundex code in files for fast compares, but also use LEFT$(x$, 1)
or the first letter for alphabetical reference.
Copyright (C) InfoSoft, 1986-1990, 1991 70
Name: StatLine Type: FUNCTIONs
(PrintStatL, CLX and SetBVLine are thoroughly covered in
MACROxx.DOC).
Name: StrLenMax/StrLeMin Type: FUNCTION(s)
Syntax: Min = StrLenMax(BYVAL(VARPTR(Array$(x))), Quan)
Max = StrLenMax(BYVAL(VARPTR(Array$(x))), Quan)
Passed a string array, these will scan the array up to Quan number
of elements (the whole array or just a portion), to find either the
longest or shortest string length. This is much faster and more
compact than fashioning loops in BASIC. Take care that the Quan
parameter will not tell StrLen--- to scan beyond the limits of the
array or invalid results will be returned.
DECLARE FUNCTION StrLenMax(BYVAL ptr%, Quan%)
..
..
REDIM Array$(125)
..
' this will scan elements 10 to 30 to find the longest string.
MaxL = StrLenMax(VARPTR(Array$(10)), 20)
' this will scan the entire array to find the shortest string
MinL = StrLenMin(VARPTR(Array$(1)), UBOUND(Array$))
' same thing
MinL = StrLenMin(VARPTR(Array$(1)), 125)
Copyright (C) InfoSoft, 1986-1990, 1991 71
Name: SubDirCount Type: FUNCTION
Syntax: count = SubDirCount(mask$)
Count the number of subdirectories matching a given mask. This
counts the number of files with the directory attribute in the default
directory. Note that while it is unusual, a directory CAN have an
extension. Example:
DirCnt = SubDirCount("*.*")
Name: SubDirCH Type: FUNCTION
Name: SubDirMK Type: FUNCTION
Name: SubDirRM Type: FUNCTION
Syntax: errc = SubDirCH(SubDirName$)
errc = SubDirMK(SubDirName$)
errc = SubDirRM(SubDirName$)
Changes (SubDirCH), Makes (SubDirMK) or Removes (SubDirRM) the sub
directory specified by SubDir$. The advantage over BASIC's native
CHDIR is that if any error is encountered, rather than an error
condition being forced on your code, an error code is returned. The
return code is set (non zero) if an error is encountered.
Name: SubDirExist Type: FUNCTION
Syntax: RetCode = SubDirExist(mask$)
Returns a non zero value if a given sub directory exists, and zero
if it does not. Example:
IF SubDirExists("QB45") THEN
CHDIR "QB45"
ELSE
PRINT "No can do"
END IF
Name: SubDirGet Type: FUNCTION
Syntax: CurDir$ = SubDirGet$
Returns a string representing the current, default directory. .
Name: SubDirList Type: FUNCTION
Syntax: ErrCode = SubDirList(mask$, VARPTR(DirNames$(x)))
SubDirList works almost identically to the function Dir, except it
fetches filenames that bear the directory attribute into the string
array. By passing a mask, it allows you to optionally get only those
names that your program has created or controls; ie FooBar.EXE
creates, gets and uses \FBData, \FBPrntr and \FBReports, so the mask
would be \FB*.*. Also note that directories can have dots in the
name.
Copyright (C) InfoSoft, 1986-1990, 1991 72
Name: SysTicks Type: FUNCTION
Syntax: TicksSoFar& = SysTicks&
SysTicks returns the number of clock ticks that have elapsed since
midnight. This allows for an even finer resolution of time that
SysTime or TIMER. Note that SysTicks returns a LONG integer.
Name: SysTime Type: SUB
Syntax: CALL SysTime(hrs, mins, secs, hund)
Rather than tearing apart BASIC's TIME$ with MID$ to determine
the current hour, minute, second, SysTime allows instant access to all
that PLUS the hundredths of a second with no string garbage generated.
Note that earlier clone BIOSes may not return hundredths of a second,
so it may not be accurate on all systems.
Name: TFRMAT Type: SUB (BASIC)
Syntax: CALL TFrmat(nutime$, mode)
TFRMAT allows for Time string formatting similar to that in
DFRMAT. There is no error checking that a valid time is passed, but
if the mode parameter is not set right, an error message of: " Invalid
mode specified" will be returned in T$, also m will be set to 50. The
parameter MODE controls the optional label - 0 = OFF / none, 1 =
"am" / "pm" whichever is appropriate
Example: Output:
PRINT TIME$ 13:01:01
CALL tfrmat(nutime$,1)
PRINT nutime$ 1:01 pm
Name: TimerToggle Type: SUB
Syntax: CALL TimerToggle(TimerNum, Toggle)
TimerToggle and TimerElapsed provide for an assembler based medium
resolution set of timers. The granularity of these timers is approx-
imately 976 milliseconds. These Timer---- functions allow for 5 dif-
ferent time slots so that you can track several different processes.
When invoking TimerToggle, TimerNum should be 1 to 5 indicating the
timer to toggle (a number less than one or more than 5 should exit
doing nothing.) The Toggle parameter indicates whether you are
starting or stopping that timer: 0 HALTS or stops the timer, any other
value starts it. If a given timer has already been started, issuing
another START command for that timer causes the previous start time to
be overwritten - that is a timer cannot be RE-started. See also
TimerElapsed&.
Copyright (C) InfoSoft, 1986-1990, 1991 73
Name: TimerElapsed& Type: FUNCTION
Syntax: ProcTime& = TimerElapsed&(TimerNum)
Fetches the number of elapsed clock ticks since the specified
timer was started. If the timer was never started, garbage is ret-
urned. TimerNum refers to an integer 1 to 5 indicating which timer
elapsed time is to be returned. TimerElapsed& returns a LONG INTEGER,
so be sure to use the right data type. Also TimerElapsed& does not do
an implicit timer stop function, it merely returns the difference of
the start and stop ticks for that timer.
Example:
CALL TimerToggle(1,1) ' start timer one
..
CALL TimerToggle(1,0) ' stop timer one
ProcTime& = TimerElapsed&(1) ' get elapsed timer ticks
' into ProcTime&
Name: TimeSquare Type: FUNCTION (BASIC)
Syntax: KeyPress = TimeSquare(Msg$(), Row, Col, Attr, Cycles)
This flashy little number provides a revolving display of messages
from the array passed simulating the marquee/reader board found in
Times Square, NYC. TimeSquare returns after Cycles number of complete
displays have been completed or a key is pressed. Parameters:
Msg$() - The string array of messages to display
Row, Col - Row and column for the message(s) display
Attr - Attribute for the message display
Cycles - Determine the number of complete cycles for the
collection of messages. If set to less than
one, the complete set of messages is displayed at
least one time before a keypress will interrupt it.
If Cycles is negative and no key is ready after the
first rotation, the display continues until
ABS(cycles) have been displayed.
TimeSquare requires QPrint, KeyReady and Delay18. Use
Save/RestWindow to restore the section of screen disturbed by
TimeSquare.
Copyright (C) InfoSoft, 1986-1990, 1991 74
Name: Translate Type: FUNCTION
Syntax: errc = Translate(source$, table$)
TRANSLATE can also be called by the name XLATE
This will translate or substitute all characters in SOURCE$ from
the list of characters in TABLE$ based on their ASCII value. Note
that since this may be as high as 255, that TABLE$ should allow for
all possibilities and be 256 characters long. This provides for an
easy and configurable encryption scheme.
Example:
FOR x = 1 to 256
Table$ = Table$ + CHR$(256 - x)
NEXT x
Serial$ = "123456"
errc = Translate(Serial$, Table$)
The result is that '1' becomes ASCII 206 because TABLE$ is the
ASCII table backwards. So '1' is 49 and 255 - 32 = 206.
Name: ValidDrv Type: FUNCTION
Syntax: result = ValidDrv(drv$)
ValidDrv tests a given character passed to see if it is possibly a
valid drive character. The return is 0 or non zero indicating if the
drive is valid and available. The spectacular thing about this
function is that it returns LOGICAL, not just physical drives, so that
if the DOS version is greater than 3.0, if SUBST or networking soft-
ware are in use, ValidDrv will return correct information - this is
done by accessing the IOCTL functions if DOS 3.0 or greater is active.
The only possible non true return would be drive B: in which, the
system recognizes A: as B: when only one floppy is installed.
Example:
DECLARE FUNCTION ValidDrv%(a$)
..
..
FOR x = 1 TO 26
PRINT CHR$(x+64);
IF ValidDrv(CHR$(x+64)) THEN
PRINT " is a valid, active drive letter."
ELSE
PRINT " is not a valid drive letter."
END IF
NEXT x
Copyright (C) InfoSoft, 1986-1990, 1991 75
Name: VerifyGet Type: FUNCTION
Syntax: vflag = VerifyGet
Returns the current VERIFY setting of the system. This is NOT
a read-after-write test as some think, but is where DOS does a CRC
check of data just written to make sure it is the same as that of the
original data. To CHANGE the VERIFY switch, use VerifySet (qv). This
routine returns 0 for OFF, non zero for ON.
Name: VerifySet Type: SUB
Syntax: CALL VerifySet(vflag)
Sets or resets the DOS VERIFY switch (see GetVerify for an explan-
ation of VERIFY). Note that if you intend to alter such a system
switch, it is good programming practice to restore it to its original
setting when your program terminates, this switch can be determined
via VerifyGet. In calling VerifySet, 0 turns VERIFY OFF, 1 turns it
ON. Example:
CALL VerifyGet(0)
CALL VerifySet(1)
Name: VFName Type: FUNCTION
Syntax: errc = VFName(fil$, DOSCode)
VFName may also be called as ValidFileName
VFNAME checks a string you pass it to determine if the string
indeed is capable of being a valid filename. Pre testing a string
that you may have gotten from end user input, helps avoid runtime
errors later on and in the case of novice end users allows consid-
erable feedback from your program on what is wrong with a filename
typed in.
The process is twofold - it tests for characters such as ,[><
and also attempts to open the file and returns 2 error codes. In the
case of the character test, the FUNCTION returns 0 (in errc) if it
finds no offending characters, or the ASCII value of any invalid
filename character. This allows you to be able to give apparently
intuitive feedback to users on valid filename characters.
A second pass is needed to test drive and path validity. The
colon and backslash are not tested as invalid chars since they ARE
valid IF in the right spot. To test this, VFNAME attempts to open or
create the file thus returning info on the path, access and if the
file already exists. Any DOS feedback is returned as the formal
parameter DOSCode.
3 - Drive or path not found
4 - No handle available ("Too Many Files")
5 - Access denied (already opened on multi system)
80 - file exists.
NOTES:
1) VFNAME does NOT actually create or open the file! It just
pre-tests for any possible runtime error in trying to do so.
2) VFNAME requires DOS 3.x
Copyright (C) InfoSoft, 1986-1990, 1991 76
Name: VidInfo Type: SUB
Syntax: CALL VidInfo(NumRows, NumCols, Mode, Page, PgSize)
With the advent of the more advanced video subsystems, the pro-
grammer can no longer make certain assumptions such as number of rows
or columns. VidInfo attempts to return much of the information
available on the current settings:
NumRows - The number of rows in the current mode.
NumCols - The number of video columns.
Mode - The Video mode. This has little to do with the
BASIC SCREEN statement - it is the DOS video mode.
Page - The current active page.
PgSize - The size in bytes of the active page.
See also VidType, VTypeSet and VTypeClr
Name: VidOff/VidOn Type: SUB
Syntax: CALL VidOn
Similar to a screen saver program, this routine will turn off
any monitor (tested on CGA, EGA, MDA and VGA). If a timing loop in
your long running program senses no activity for x minutes, a call to
VIDOFF will turn off the display, then once you sense activity again,
VIDON restores the display.
Note: VidOn / VidOff will only toggle the video output on a VGA
system equipped with both a VGA adapter AND a VGA monitor. Some
'super' VGA cards that can drive any monitor may not respond to this
depending on what mode or type of emulation they are performing.
Name: VidType Type: FUNCTION
Syntax: crt = VidType
No routine can tell you the type of display attcahed to a com-
puter, but routines such as VidType CAN tell you the type of video
display card installed. As such, VidType returns an integer code to
identify the active video card and/or mode:
0 = MONO 4 = EGA Mono 8 = VGA Mono
1 = Herc, Herc Plus 5 = EGA Color 9 = VGA Color
2 = Herc Incolor 6 = MCGA Mono
3 = CGA 7 = MCGA Color
Note that on multiple display systems, the active display is
identified on EGA/VGA systems, while the primary one is identified on
CGA/Mono multiple display systems. Also, some "Super VGA" cards
connected to Multi Synch monitors, may identify the Multi Sych system
as an EGA. This is dependant on the BIOS compatibility of the card.
See also VTypeSet and VTypeClr
Copyright (C) InfoSoft, 1986-1990, 1991 77
Name: VidPageCsr Type: SUB
Syntax: CALL VidPageCsr(page, row, col)
This fetches the correct row, column coordinates for a requested
video page. No error checking is done for a VALID page, but when
called from a loop, it can quickly fetch the cursor location for any
and all pages. Example: Get Cursor locations into array
FOR x = 1 to MaxPages
CALL VidPageCsr(x, Csr(x,1), Csr(x,2) )
NEXT x
Name: VLabelGet/VLabelSet Type: FUNCTION
Syntax: MyLabel$ = VLabelGet$
errc = VLabelSet(NewVLabel$)
Allows you to get or set the disk volume label. The maximum size
allowed for a label is 11 characters. VLabelSet will only use the
first 11 of whatever you pass (pass SPACE$(11) to clear the name). A
return code of -1 indicates and error.
Name: VTypeSet/VTypeClr Type: FUNCTION and SUB
Syntax: errc = VTypeSet(ColorType, TraceFlag) (Function)
CALL VTypeClr (SUB)
These sub programs allow you to override or tailor the video sub
system detection code used internally by virtually all of the GLib
video routines (Painter, Windows, Boxes, QPrint etc). At times it may
be desirable override the default systems detected. For example a
very high quality CGA may not need video retrace performed (ie 'snow
removal'), VTypeSet would allow you to instruct most all video sub
programs to skip such retrace checking. Of course, in this case,
there is no way for your code to tell if the snow removal is needed
without asking the end user.
Another example is in odd video cards such as a "CGA Emulator":
in using VTypeSet, you can force output to the MONO or COLOR video
segments as need by these. Finally, the very high-res EGA cards used
on early Model 80's for ACAD and such _are_ color systems, yet they
return a code indicating a MONO sub system (on purpose I am told).
Using VTypeSet allows you to force output to the color segment.
Parameters:
ColorType: 0 causes output to the Mono video segment;
1 forces output to the color segment
Any other value causes an error to be returned.
TraceFlag: 0 eliminates video retrace checking ("snow removal")
1 forces it to be used regardless of the video sub system
See Note below
Copyright (C) InfoSoft, 1986-1990, 1991 78
VTypeClr clears the overrides that you set with VTypeSet and
instructs GLib video sub programs to act based on the video sub system
detected by it's internal detection routines.
Notes:
1.) Since VTypeSet overrides the defaults, no error or integrity
checking performed. Setting the TraceFlag (1) and the ColorType
to MONO (0) may hang the system for a variety of reasons. The
TraceFlag should only be set when the ColorType is set to Color
(1) _AND_ there is indeed a color subsystem installed and
active. Setting the TraceFlag with a EGA or VGA system will
cause it to hang as there is never a high or low return from the
retrace port - it is non-existant!
2.) Wise use of this can also be used to slow down the grow effect
of WINDOWS and possibly provide a method of adjusting the GROW
factor. By setting the TraceFlag to 1 (on CGA systems) and
forcing video retrace, just the right amount of delay may be
added to the growing of the WINDOWS.
Copyright (C) InfoSoft, 1986-1990, 1991 79
Name: Windows Type: SUB
Syntax: CALL Windows(TR, LC, BR, RC, SFX, Grow, Frame, Attr,_
label$)
An extensive windowing routine, allows you to fully control
frames, sound, color and grow effect. The routine requires numerous
arguments passed. Be warned that NO error checking takes place as to
accurate or misplaced coordinates - really far out coordinates can
lock up the machine (such as locating the bottom of the window ABOVE
the top etc...).
Frames: WINDOWS comes with virtually an unlimited number of frame
styles with the five most common 'built in':
0 - Spaces used / no frame
1 - Double Lines Horizontal / Double Lines Vertical
2 - Double Lines Horizontal / Single Lines Vertical
3 - Single Lines Horizontal / Single Lines Vertical
4 - Single Lines Horizontal / Double Lines Vertical
Invoking WINDOWS with the frame style set to 5 tells WINDOWS
to use the user defined character set for the frame as defined
by the WSetUDef sub program (qv). An unrecognized frame style
code such as anything over 5 or 5 if there is no user defined
frame style defined, will default to type 0 - spaces/no frame.
Grow: By setting the GROW parameter to ZERO, the window simply
appears on the screen. Non Zero indicates you want a growing
effect and controls the grow speed: the larger the number, the
slower the growing. Other grow effect factors:
o Video Sub system: This is more a factor than the CPU
type or speed: A 25 MHz 386 with a CGA will need about
the same grow factor as a 6 Mhz 286 and a 8088 PC also
with a CGA will require a similar GROW factor, more so
than if it has a VGA.
o WINDOW Size and Shape. A tall, but narrow window
may need a different delay value than a very wide but
short one.
o Each increment of one invokes a delay of 1 clock tick.
This may not sound like much, and indeed in the grand
scheme of things it is not, but in the context of 18 to
24 redrawings of a window it can be a lot. Our testing
on VGA and fast 286 systems showed that GROW factor
values of 1, 2 and 3 were plenty to slow down the delay
a speed at which it can be perceived. Too long of a
delay makes the CHIRP sound incongruent and the growing
look 'funny'.
Other Parameters:
TR - Top row of window to be displayed.
LC - Left border of window to be displayed.
BR - Bottom row of window to be displayed.
RC - Right border of window.
SFX - Sound effects toggle, 0=OFF 1=ON
Grow - Grow switch, 0 = No grow, Non Zero = Grow Speed
Frame - Style of frame to use for the window
Attr - Attribute of window (See also MakeAttr)
Label$- Label to center across the top of the window, for no label
use ""
Copyright (C) InfoSoft, 1986-1990, 1991 80
Example:
tr=2 : lc=2
br=5 : rc=79
sfx=1 : gro=1 : frame=1
attr=78
label$=" A long window across the top of the screen "
CALL Windows(tr, lc, br, rc, sfx, gro, frame, attr, l$)
or
CALL windows(2, 2, 5, 45, 0, 1, 4, 64, "")
Puts a window to the screen from 2,2 to 5,79, with a chirp sound
effect, with a double / double line frame with a yellow foreground on
a red background.
Other sub programs that control or add to WINDOWS or can be used
with it include: WShadow, MakeAttr, Chirp, BufCalc, VTypeSet and
SaveScrn
Name: WSetUDef Type: SUB
Syntax: CALL WSetUdef(TL, TR, BL, BR, VChar, HChar)
WINDOWS has 5 built in, or default frame styles, however in cer-
tain situations, you may want to define your own via WSetUDef. Once
defined they may be used over and over; that is, you need not call
WSetUDef over and over to set the same User Defined frame style for
each call to WINDOWS. The User Defined type can be changed later with
another call to WSetUDef. The parameters sent to WSetUDef are in-
tegers representing the ASCII value of the character to use for the
Top Left corner, Top Right corner, Bottom Left corner, Bottom Right
corner, Vertical character and Horizontal character respectively.
Example:
' Set Window frames to "?"
CALL WSetUDef(63, 63, 63, 63, 63, 63)
..
..
' make growing window, with no sound with "?????" frame style
CALL Windows(5, 5, 18, 45, 0, 1, 5, 78, " Test ")
' change user defined box characters to 'test' on frame style
' (+-|):
CALL WsetUDef(43, 43, 43, 43, 124, 45)
..
..
CALL Windows(5, 5, 18, 45, 0, 1, 5, 78, "Text")
Copyright (C) InfoSoft, 1986-1990, 1991 81
Name: WShadow Type: SUB
Syntax: CALL WShadow(Flag)
This sets a global flag to indicate to the Windows routine whether
or not it is to draw the window with a shadow or '3-D' effect around
it. By 'global', we mean all future calls to Windows, whether from
your main code module or from inside a sub, will respect the setting
of the flag.
By making this shadowing effect a separate call, we avoid adding a
parameter to the Window call that invalidates thousands of lines of
code that are already written as documented above. Shadow Parameter:
0 = Off - no shadowing
1 = Shadowing ON - Place shadow on bottom and right side
of window.
-1 = Shadowing ON - Place shadow on bottom and left side of
window.
This shadow effect basically washes out the underlying colors - not a
simple string of spaces in color 0 that others will try to tell you is
a shadow. If you hold a paper half-in and half-out of a shadow, you
can still see the portion in the shade - just the tones and hues
change!
The size of the window frame is unaffected by WShadow, but one
more screen row and one more column is altered, and should be taken
into consideration when saving a portion of the screen (ie:
SaveWindow).
Once set, the shadow is automatically displayed with every sub-
sequent call to Windows. If you always use a shadow and want it on
the right, 'CALL WShadow(1)' is all you need to add to your code - all
Window calls after that will have a shadow on the right.
Thru the course of your program, WShadow can be changed to move
the shadow to the other side or halt it and reactivate it, but only
future calls to Windows are affected.
Copyright (C) InfoSoft, 1986-1990, 1991 82
Acknowledgements
Advanced MS DOS Programming, MS-DOS Functions and IBM ROM BIOS
all by Ray Duncan
Norton Guides For Assembler
Programmers Guide to PC and PS/2 Video Systems by Richard Wilton
Programming Problem Solver Handbook by Robert Jordain
Assembly Language Subroutines by Leo J Scanlon
Interrupt List - A file of undocumented or poorly documented
interrupts found on BBSes everywhere.
MS-DOS Encyclopedia published by Microsoft Press, edited by
Ray Duncan
System BIOS for IBM PC/XT/AT computers and compatibles
by Phoenix Technologies
The basic timekeeping function and framework of CLOCK is based on
CLOCK.ASM PC Magazine Vol 6 No 17. Our enhancements include the 12
hour display format, label, secondary timing loop to adjust the
accuracy and the tone that sounds on the hour and half hour.
QCALC is based on a Floating Point Calculator in 'C' (author
unknown) and CALC.COM (A TSR pop up calculator) from Vol 7 No 6 of PC
Magazine. Our modifications include making it locatable, the display
appearance, the blinking buttons and speed parameter, and making it
callable from "C" or "QB" and returning a long
integer to either.
Finally, if you are interested in ASM level programming or just
plain tinkering, the Microsoft KnowledgeBase is invaluable. When many
of the normal interface items changed in QB4, they are not completely
covered in the Mixed Language Programming Guide, but many extended
explanations and examples are in the KnowledgeBase. Information for
passing Fixed Length String arrays as well as string arrays to ASM
routines that is radically different in QB4 and QBX (BASIC PDS), for
instance, that made DirA and DIRF possible came from there.
Copyright (C) InfoSoft, 1986-1990, 1991 83